ESXi-5.5-U1

This commit is contained in:
unknown 2015-10-23 18:29:35 -04:00
parent 91e0d39c98
commit 89a4bb14d0
79 changed files with 21997 additions and 8736 deletions

View file

@ -251,13 +251,8 @@ typedef struct vmk_EthHdr {
typedef struct vmk_VLANHdr {
/** High four bits of the VLAN ID. */
vmk_uint8 vlanIDHigh:4;
/** This field has two different interpretations. */
union {
/** The MAC addresses are in canonical format. */
vmk_uint8 canonical:1;
/** The frame is eligible to be dropped in the presence of congestion. */
vmk_uint8 dropEligible:1;
};
/** The frame is eligible to be dropped in the presence of congestion. */
vmk_uint8 dropEligible:1;
/** Priority tag. */
vmk_uint8 priority:3;
/** Low eight bits of the VLAN ID. */

View file

@ -251,13 +251,8 @@ typedef struct vmk_EthHdr {
typedef struct vmk_VLANHdr {
/** High four bits of the VLAN ID. */
vmk_uint8 vlanIDHigh:4;
/** This field has two different interpretations. */
union {
/** The MAC addresses are in canonical format. */
vmk_uint8 canonical:1;
/** The frame is eligible to be dropped in the presence of congestion. */
vmk_uint8 dropEligible:1;
};
/** The frame is eligible to be dropped in the presence of congestion. */
vmk_uint8 dropEligible:1;
/** Priority tag. */
vmk_uint8 priority:3;
/** Low eight bits of the VLAN ID. */

View file

@ -1,6 +1,6 @@
#define BUILD_NUMBER "build-1604073"
#define BUILD_NUMBER_NUMERIC 1604073
#define BUILD_NUMBER_NUMERIC_STRING "1604073"
#define PRODUCT_BUILD_NUMBER "product-build-4509"
#define PRODUCT_BUILD_NUMBER_NUMERIC 4509
#define PRODUCT_BUILD_NUMBER_NUMERIC_STRING "4509"
#define BUILD_NUMBER "build-1623387"
#define BUILD_NUMBER_NUMERIC 1623387
#define BUILD_NUMBER_NUMERIC_STRING "1623387"
#define PRODUCT_BUILD_NUMBER "product-build-4950"
#define PRODUCT_BUILD_NUMBER_NUMERIC 4950
#define PRODUCT_BUILD_NUMBER_NUMERIC_STRING "4950"

View file

@ -1,8 +1,13 @@
The following assumes the files disclosed for this package have been
copied to the directory "/usr/vmware/src", and any commands that need to
be executed for the disclosure should be executed from this directory
on a "centos-5.3-x64" system (see the file "SYSTEMS.txt" for definition
of this system).
copied to the directory "/usr/vmware/src":
rm -rf /usr/vmware/src
mkdir /usr/vmware/src
cp * /usr/vmware/src
And any commands that need to be executed for the disclosure should be
executed from this directory on a "centos-5.3-x64" system (see the file
"SYSTEMS.txt" for definition of this system).
This package should be built on a "centos-5.3-x64" system. Please see the
"System Configurations" document for a definition of the configuration

26
machines.cfgx Normal file
View file

@ -0,0 +1,26 @@
<verify>
<virtual-infrastructure>
<address>10.111.110.45</address>
<username>root</username>
<password>password</password>
<vm type="build">
<id>centos-5.3-x64</id>
<realname>Rush-CentOS-5.3-x64</realname>
<os>linux</os>
<username>root</username>
<password>welcome</password>
</vm>
</virtual-infrastructure>
<virtual-infrastructure>
<address>10.111.110.98</address>
<username>root</username>
<password>welcome</password>
<vm type="install">
<id>BDE-Management-Server</id>
<realname>management-server</realname>
<os>linux</os>
<username>root</username>
<password>vmware</password>
</vm>
</virtual-infrastructure>
</verify>

26
vmkdrivers-gpl.odpx Normal file
View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<disclosure>
<name>vmkdrivers</name>
<version>gpl</version>
<category>VMWsource</category>
<build>
<target>centos-5.3-x64</target>
<files>
<file>vmkdrivers-gpl.tgz</file>
<file>collect-drivers.sh</file>
<file>update-drivers.sh</file>
</files>
<process>
<execute>tar xzf vmkdrivers-gpl.tgz</execute>
<execute>sh ./build-vmkdrivers.sh</execute>
<execute>mv collect-drivers.sh BLD/build/collect-drivers.sh</execute>
<execute>cd BLD/build</execute>
<execute>./collect-drivers.sh</execute>
</process>
<deliveries>
<delivery dir="BLD/build">drivers</delivery>
<delivery>update-drivers.sh</delivery>
</deliveries>
<output>centos-5.3-x64</output>
</build>
</disclosure>

View file

@ -1,5 +1,5 @@
/*
* Portions Copyright 2008 - 2010 VMware, Inc.
* Portions Copyright 2008 - 2013 VMware, Inc.
*/
/*
* ahci.c - AHCI SATA support
@ -54,7 +54,7 @@
#endif
#define DRV_NAME "ahci"
#define DRV_VERSION "3.0-17vmw"
#define DRV_VERSION "3.0-18vmw"
#if defined(__VMKLNX__)
static int ahci_skip_host_reset = 0;
@ -634,6 +634,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
@ -1968,7 +1971,6 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
#if defined(__VMKLNX__)
if ((irq_stat & PORT_IRQ_PHYRDY) && (ap->link.device[0].sdev)) {
vmklnx_scsi_device_hot_removed(ap->link.device[0].sdev);
ata_ehi_push_desc(host_ehi, "hotplug handled");
}
#endif

View file

@ -91,7 +91,7 @@
#include "bnx2_fw2.h"
#define DRV_MODULE_NAME "bnx2"
#define DRV_MODULE_VERSION "2.2.3h.v55.2"
#define DRV_MODULE_VERSION "2.2.3d.v55.2"
#define DRV_MODULE_RELDATE "Feb 12, 2013"
#define RUN_AT(x) (jiffies + (x))

View file

@ -15,7 +15,7 @@
#ifndef CNIC_REGISTER_H
#define CNIC_REGISTER_H
#define CNIC_REGISTER_MODULE_VERSION "1.72.2.v55.1"
#define CNIC_REGISTER_MODULE_VERSION "1.72.1.v50.1i"
#define CNIC_REGISTER_MODULE_RELDATE "February 06, 2013"
extern int cnic_register_adapter(const char * name, void *callback);
extern void *cnic_register_get_callback(const char * name);

View file

@ -15,7 +15,7 @@
#ifndef CNIC_REGISTER_H
#define CNIC_REGISTER_H
#define CNIC_REGISTER_MODULE_VERSION "1.72.2.v55.1"
#define CNIC_REGISTER_MODULE_VERSION "1.72.1.v50.1i"
#define CNIC_REGISTER_MODULE_RELDATE "February 06, 2013"
extern int cnic_register_adapter(const char * name, void *callback);
extern void *cnic_register_get_callback(const char * name);

View file

@ -997,6 +997,14 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
reg |= (1 << 28);
ew32(TARC(1), reg);
/*
* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
reg = er32(RFCTL);
reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
ew32(RFCTL, reg);
return;
}

View file

@ -1184,6 +1184,16 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
ew32(CTRL_EXT, reg);
}
/*
* Disable IPv6 extension header parsing because some malformed
* IPv6 headers can hang the Rx.
*/
if (hw->mac.type <= e1000_82573) {
reg = er32(RFCTL);
reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
ew32(RFCTL, reg);
}
/* PCI-Ex Control Registers */
switch (hw->mac.type) {

View file

@ -2785,6 +2785,21 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
ew32(STATUS, reg);
}
/*
* work-around descriptor data corruption issue during nfs v2 udp
* traffic,just disable the nfs filtering capability
*/
reg = er32(RFCTL);
reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
/*
* Disable IPv6 extension header parsing because some
* malformed IPv6 headers can hang the Rx.
*/
if (hw->mac.type == e1000_ich8lan)
reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
ew32(RFCTL, reg);
return;
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -28,10 +28,10 @@
#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))
#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
@ -42,149 +42,150 @@
* 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_SW_SYNCH_MB 0x00000100
#define E1000_STAT_DEV_RST_SET 0x00100000
#define E1000_CTRL_DEV_RST 0x20000000
#define E1000_RAR_ENTRIES_I350 32
#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 */
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 */
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 */
#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 */
#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;
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;
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_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_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_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_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_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_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)
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)
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 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)
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 */
#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 */
__le64 pkt_addr; /* Packet buffer address */
__le64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
@ -192,79 +193,79 @@ union e1000_adv_rx_desc {
__le32 data;
struct {
__le16 pkt_info; /*RSS type, Pkt type*/
__le16 hdr_info; /* Split Header,
* header buffer len*/
/* Split Header, header buffer len */
__le16 hdr_info;
} hs_rss;
} lo_dword;
union {
__le32 rss; /* RSS Hash */
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
__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 */
__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
#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_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_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_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 */
#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_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
#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 {
@ -281,25 +282,26 @@ union e1000_adv_tx_desc {
};
/* 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 packet */
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
#define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED present 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 */
#define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800 /* 1st&Last TSO-full iSCSI PDU*/
#define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
#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 {
@ -309,65 +311,69 @@ struct e1000_adv_tx_context_desc {
__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 */
#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
#define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000 /* Req requires Markers and CRC */
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
#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
#define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF
/* Adv ctxt IPSec ESP len mask */
#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF
#define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF
/* Additional Transmit Descriptor Control definitions */
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
#define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. write-back flushing */
#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
#define E1000_TXDCTL_PRIORITY 0x08000000
/* Additional Receive Descriptor Control definitions */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
#define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. write-back flushing */
#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_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_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 enable */
#define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
#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_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx Desc Relax Order */
#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 0x0000001F /* Tx CPUID Mask */
#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */
#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 */
#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 */
#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)
#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
@ -376,76 +382,128 @@ struct e1000_adv_tx_context_desc {
* Current filters:
* EAPOL 802.1x (0x888e): Filter 0
*/
#define E1000_ETQF_FILTER_EAPOL 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_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 8
#define E1000_NVM_APME_82575 0x0400
#define MAX_NUM_VFS 7
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
#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 */
#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)
#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)
#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_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_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_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_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
#define E1000_PBRWAC_WALPB 0x00000007 /* Wrap around event on LAN Rx PB */
#define E1000_PBRWAC_PBE 0x00000008 /* Rx packet buffer empty */
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
#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_IOVCTL 0x05BBC
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
#define E1000_RPLOLR_STRVLAN 0x40000000
#define E1000_RPLOLR_STRCRC 0x80000000
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
#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_IOVCTL 0x05BBC
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
#define ALL_QUEUES 0xFFFF
#define E1000_RPLOLR_STRVLAN 0x40000000
#define E1000_RPLOLR_STRCRC 0x80000000
/* RX packet buffer size defines */
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
#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_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data);
s32 e1000_set_eee_i350(struct e1000_hw *);
s32 e1000_set_eee_i354(struct e1000_hw *);
s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *);
#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_ */

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -157,7 +157,7 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82576_FIBER:
case E1000_DEV_ID_82576_SERDES:
case E1000_DEV_ID_82576_QUAD_COPPER:
case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
case E1000_DEV_ID_82576_NS:
case E1000_DEV_ID_82576_NS_SERDES:
case E1000_DEV_ID_82576_SERDES_QUAD:
@ -168,14 +168,39 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82580_SERDES:
case E1000_DEV_ID_82580_SGMII:
case E1000_DEV_ID_82580_COPPER_DUAL:
case E1000_DEV_ID_82580_QUAD_FIBER:
case E1000_DEV_ID_DH89XXCC_SGMII:
case E1000_DEV_ID_DH89XXCC_SERDES:
case E1000_DEV_ID_DH89XXCC_BACKPLANE:
case E1000_DEV_ID_DH89XXCC_SFP:
mac->type = e1000_82580;
break;
case E1000_DEV_ID_I350_COPPER:
case E1000_DEV_ID_I350_FIBER:
case E1000_DEV_ID_I350_SERDES:
case E1000_DEV_ID_I350_SGMII:
case E1000_DEV_ID_I350_DA4:
mac->type = e1000_i350;
break;
case E1000_DEV_ID_I210_COPPER_FLASHLESS:
case E1000_DEV_ID_I210_SERDES_FLASHLESS:
case E1000_DEV_ID_I210_COPPER:
case E1000_DEV_ID_I210_COPPER_OEM1:
case E1000_DEV_ID_I210_COPPER_IT:
case E1000_DEV_ID_I210_FIBER:
case E1000_DEV_ID_I210_SERDES:
case E1000_DEV_ID_I210_SGMII:
mac->type = e1000_i210;
break;
case E1000_DEV_ID_I211_COPPER:
mac->type = e1000_i211;
break;
case E1000_DEV_ID_I354_BACKPLANE_1GBPS:
case E1000_DEV_ID_I354_SGMII:
case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS:
mac->type = e1000_i354;
break;
default:
/* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT;
@ -189,10 +214,10 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
* e1000_setup_init_funcs - Initializes function pointers
* @hw: pointer to the HW structure
* @init_device: true will initialize the rest of the function pointers
* getting the device ready for use. false will only set
* MAC type and the function pointers for the other init
* functions. Passing false will not generate any hardware
* reads or writes.
* getting the device ready for use. false will only set
* MAC type and the function pointers for the other init
* functions. Passing false will not generate any hardware
* reads or writes.
*
* This function must be called by a driver in order to use the rest
* of the 'shared' code files. Called by drivers only.
@ -232,8 +257,13 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_82576:
case e1000_82580:
case e1000_i350:
case e1000_i354:
e1000_init_function_pointers_82575(hw);
break;
case e1000_i210:
case e1000_i211:
e1000_init_function_pointers_i210(hw);
break;
default:
DEBUGOUT("Hardware not supported\n");
ret_val = -E1000_ERR_CONFIG;
@ -320,11 +350,11 @@ void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count)
u32 mc_addr_count)
{
if (hw->mac.ops.update_mc_addr_list)
hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
mc_addr_count);
mc_addr_count);
}
/**
@ -618,20 +648,6 @@ s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
return E1000_SUCCESS;
}
/**
* e1000_mta_set - Sets multicast table bit
* @hw: pointer to the HW structure
* @hash_value: Multicast hash value.
*
* This sets the bit in the multicast table corresponding to the
* hash value. This is a function pointer entry point called by drivers.
**/
void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
{
if (hw->mac.ops.mta_set)
hw->mac.ops.mta_set(hw, hash_value);
}
/**
* e1000_hash_mc_addr - Determines address location in multicast table
* @hw: pointer to the HW structure
@ -672,14 +688,10 @@ bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
* 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(struct e1000_hw * hw, u8 *buffer, u16 length,
u16 offset, u8 *sum)
s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
u16 offset, u8 *sum)
{
if (hw->mac.ops.mng_host_if_write)
return hw->mac.ops.mng_host_if_write(hw, buffer, length,
offset, sum);
return E1000_NOT_IMPLEMENTED;
return e1000_mng_host_if_write_generic(hw, buffer, length, offset, sum);
}
/**
@ -690,12 +702,9 @@ s32 e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer, u16 length,
* Writes the command header after does the checksum calculation.
**/
s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
struct e1000_host_mng_command_header *hdr)
struct e1000_host_mng_command_header *hdr)
{
if (hw->mac.ops.mng_write_cmd_header)
return hw->mac.ops.mng_write_cmd_header(hw, hdr);
return E1000_NOT_IMPLEMENTED;
return e1000_mng_write_cmd_header_generic(hw, hdr);
}
/**
@ -708,27 +717,9 @@ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
* 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(struct e1000_hw * hw)
s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
{
if (hw->mac.ops.mng_enable_host_if)
return hw->mac.ops.mng_enable_host_if(hw);
return E1000_NOT_IMPLEMENTED;
}
/**
* e1000_wait_autoneg - Waits for autonegotiation completion
* @hw: pointer to the HW structure
*
* Waits for autoneg to complete. Currently no func pointer exists and all
* implementations are handled in the generic version of this function.
**/
s32 e1000_wait_autoneg(struct e1000_hw *hw)
{
if (hw->mac.ops.wait_autoneg)
return hw->mac.ops.wait_autoneg(hw);
return E1000_SUCCESS;
return e1000_mng_enable_host_if_generic(hw);
}
/**
@ -961,18 +952,34 @@ s32 e1000_read_mac_addr(struct e1000_hw *hw)
}
/**
* e1000_read_pba_num - Read device part number
* e1000_read_pba_string - Read device part number string
* @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.
* Currently no func pointer exists and all implementations are handled in the
* generic version of this function.
**/
s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size)
{
return e1000_read_pba_num_generic(hw, pba_num);
return e1000_read_pba_string_generic(hw, pba_num, pba_num_size);
}
/**
* e1000_read_pba_length - Read device part number string 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.
* Currently no func pointer exists and all implementations are handled in the
* generic version of this function.
**/
s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size)
{
return e1000_read_pba_length_generic(hw, pba_num_size);
}
/**
@ -1065,7 +1072,7 @@ s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
* This is a function pointer entry point called by drivers.
**/
s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset,
u8 data)
u8 data)
{
return e1000_write_8bit_ctrl_reg_generic(hw, reg, offset, data);
}
@ -1098,6 +1105,18 @@ void e1000_power_down_phy(struct e1000_hw *hw)
hw->phy.ops.power_down(hw);
}
/**
* e1000_power_up_fiber_serdes_link - Power up serdes link
* @hw: pointer to the HW structure
*
* Power on the optics and PCS.
**/
void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw)
{
if (hw->mac.ops.power_up_serdes)
hw->mac.ops.power_up_serdes(hw);
}
/**
* e1000_shutdown_fiber_serdes_link - Remove link during power down
* @hw: pointer to the HW structure
@ -1110,3 +1129,31 @@ void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw)
hw->mac.ops.shutdown_serdes(hw);
}
/**
* e1000_get_thermal_sensor_data - Gathers thermal sensor data
* @hw: pointer to hardware structure
*
* Updates the temperatures in mac.thermal_sensor_data
**/
s32 e1000_get_thermal_sensor_data(struct e1000_hw *hw)
{
if (hw->mac.ops.get_thermal_sensor_data)
return hw->mac.ops.get_thermal_sensor_data(hw);
return E1000_SUCCESS;
}
/**
* e1000_init_thermal_sensor_thresh - Sets thermal sensor thresholds
* @hw: pointer to hardware structure
*
* Sets the thermal sensor thresholds according to the NVM map
**/
s32 e1000_init_thermal_sensor_thresh(struct e1000_hw *hw)
{
if (hw->mac.ops.init_thermal_sensor_thresh)
return hw->mac.ops.init_thermal_sensor_thresh(hw);
return E1000_SUCCESS;
}

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -30,78 +30,81 @@
#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_shutdown_fiber_serdes_link(struct e1000_hw *hw);
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);
extern void e1000_init_function_pointers_i210(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);
s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr);
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);
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);
void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
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);
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);
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);
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_num(struct e1000_hw *hw, u32 *part_num);
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);
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_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_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:
@ -134,14 +137,21 @@ s32 e1000_mng_write_dhcp_info(struct e1000_hw * hw,
/* 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)))))
#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)))))
#ifndef E1000_MAX
#define E1000_MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef E1000_DIVIDE_ROUND_UP
#define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */
#endif
#endif /* _E1000_API_H_ */

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -34,41 +34,60 @@
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_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_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_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_I210_COPPER 0x1533
#define E1000_DEV_ID_I210_COPPER_OEM1 0x1534
#define E1000_DEV_ID_I210_COPPER_IT 0x1535
#define E1000_DEV_ID_I210_FIBER 0x1536
#define E1000_DEV_ID_I210_SERDES 0x1537
#define E1000_DEV_ID_I210_SGMII 0x1538
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
#define E1000_DEV_ID_I211_COPPER 0x1539
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
#define E1000_DEV_ID_I354_SGMII 0x1F41
#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45
#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_FUNC_0 0
#define E1000_FUNC_1 1
#define E1000_FUNC_2 2
#define E1000_FUNC_3 3
#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_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
#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,
@ -76,6 +95,9 @@ enum e1000_mac_type {
e1000_82576,
e1000_82580,
e1000_i350,
e1000_i354,
e1000_i210,
e1000_i211,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
@ -92,6 +114,7 @@ enum e1000_nvm_type {
e1000_nvm_none,
e1000_nvm_eeprom_spi,
e1000_nvm_flash_hw,
e1000_nvm_invm,
e1000_nvm_flash_sw
};
@ -112,6 +135,7 @@ enum e1000_phy_type {
e1000_phy_ife,
e1000_phy_82580,
e1000_phy_vf,
e1000_phy_i210,
};
enum e1000_bus_type {
@ -185,13 +209,22 @@ enum e1000_serdes_link_state {
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 csum; /* Packet checksum */
u8 status; /* Descriptor status */
u8 errors; /* Descriptor Errors */
__le16 special;
};
@ -203,9 +236,9 @@ union e1000_rx_desc_extended {
} read;
struct {
struct {
__le32 mrq; /* Multiple Rx Queues */
__le32 mrq; /* Multiple Rx Queues */
union {
__le32 rss; /* RSS Hash */
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
@ -215,12 +248,16 @@ union e1000_rx_desc_extended {
struct {
__le32 status_error; /* ext status/error */
__le16 length;
__le16 vlan; /* VLAN tag */
__le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
#define MAX_PS_BUFFERS 4
/* Number of packet split data buffers (not including the header buffer) */
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
/* Receive Descriptor - Packet Split */
union e1000_rx_desc_packet_split {
struct {
@ -229,9 +266,9 @@ union e1000_rx_desc_packet_split {
} read;
struct {
struct {
__le32 mrq; /* Multiple Rx Queues */
__le32 mrq; /* Multiple Rx Queues */
union {
__le32 rss; /* RSS Hash */
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
@ -240,12 +277,13 @@ union e1000_rx_desc_packet_split {
} lower;
struct {
__le32 status_error; /* ext status/error */
__le16 length0; /* length of buffer 0 */
__le16 vlan; /* VLAN tag */
__le16 length0; /* length of buffer 0 */
__le16 vlan; /* VLAN tag */
} middle;
struct {
__le16 header_status;
__le16 length[3]; /* length of buffers 1-3 */
/* length of buffers 1-3 */
__le16 length[PS_PAGE_BUFFERS];
} upper;
__le64 reserved;
} wb; /* writeback */
@ -257,16 +295,16 @@ struct e1000_tx_desc {
union {
__le32 data;
struct {
__le16 length; /* Data buffer length */
u8 cso; /* Checksum offset */
u8 cmd; /* Descriptor control */
__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 */
u8 status; /* Descriptor status */
u8 css; /* Checksum start */
__le16 special;
} fields;
} upper;
@ -277,37 +315,37 @@ struct e1000_context_desc {
union {
__le32 ip_config;
struct {
u8 ipcss; /* IP checksum start */
u8 ipcso; /* IP checksum offset */
__le16 ipcse; /* IP checksum end */
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 */
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 */
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 */
__le64 buffer_addr; /* Address of the descriptor's buffer address */
union {
__le32 data;
struct {
__le16 length; /* Data buffer length */
__le16 length; /* Data buffer length */
u8 typ_len_ext;
u8 cmd;
} flags;
@ -315,8 +353,8 @@ struct e1000_data_desc {
union {
__le32 data;
struct {
u8 status; /* Descriptor status */
u8 popts; /* Packet Options */
u8 status; /* Descriptor status */
u8 popts; /* Packet Options */
__le16 special;
} fields;
} upper;
@ -400,6 +438,10 @@ struct e1000_hw_stats {
u64 scvpc;
u64 hrmpc;
u64 doosync;
u64 o2bgptc;
u64 o2bspc;
u64 b2ospc;
u64 b2ogprc;
};
@ -427,7 +469,7 @@ struct e1000_host_command_header {
u8 checksum;
};
#define E1000_HI_MAX_DATA_LENGTH 252
#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];
@ -442,7 +484,7 @@ struct e1000_host_mng_command_header {
u16 command_length;
};
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
#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];
@ -454,13 +496,13 @@ struct e1000_host_mng_command_info {
#include "e1000_manage.h"
#include "e1000_mbx.h"
/* Function pointers for the MAC. */
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 *);
bool (*check_mng_mode)(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 *);
@ -473,22 +515,35 @@ struct e1000_mac_operations {
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 (*mta_set)(struct e1000_hw *, 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 *);
@ -499,18 +554,24 @@ struct e1000_phy_operations {
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);
};
/* Function pointers for the NVM. */
struct e1000_nvm_operations {
s32 (*init_params)(struct e1000_hw *);
s32 (*acquire)(struct e1000_hw *);
@ -523,10 +584,23 @@ struct e1000_nvm_operations {
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[6];
u8 perm_addr[6];
u8 addr[ETH_ADDR_LEN];
u8 perm_addr[ETH_ADDR_LEN];
enum e1000_mac_type type;
@ -554,6 +628,7 @@ struct e1000_mac_info {
u8 forced_speed_duplex;
bool adaptive_ifs;
bool has_fwsm;
bool arc_subsystem_valid;
bool asf_firmware_present;
bool autoneg;
@ -563,6 +638,7 @@ struct e1000_mac_info {
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 {
@ -624,13 +700,14 @@ struct e1000_bus_info {
};
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 */
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 */
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 {
@ -664,14 +741,20 @@ struct e1000_mbx_info {
struct e1000_dev_spec_82575 {
bool sgmii_active;
bool global_device_reset;
bool eee_disable;
bool module_plugged;
bool clear_semaphore_once;
u32 mtu;
struct sfp_e1000_flags eth_flags;
u8 media_port;
bool media_changed;
};
struct e1000_dev_spec_vf {
u32 vf_number;
u32 v2p_mailbox;
u32 vf_number;
u32 v2p_mailbox;
};
struct e1000_hw {
void *back;
@ -688,8 +771,8 @@ struct e1000_hw {
struct e1000_host_mng_dhcp_cookie mng_cookie;
union {
struct e1000_dev_spec_82575 _82575;
struct e1000_dev_spec_vf vf;
struct e1000_dev_spec_82575 _82575;
struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
@ -701,6 +784,7 @@ struct e1000_hw {
};
#include "e1000_82575.h"
#include "e1000_i210.h"
/* These functions must be implemented by drivers */
s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);

View file

@ -0,0 +1,909 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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 s32 e1000_acquire_nvm_i210(struct e1000_hw *hw);
static void e1000_release_nvm_i210(struct e1000_hw *hw);
static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw);
static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw);
static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
/**
* e1000_acquire_nvm_i210 - Request for access to EEPROM
* @hw: pointer to the HW structure
*
* Acquire the necessary semaphores for exclusive access to the EEPROM.
* 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).
**/
static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_acquire_nvm_i210");
ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
return ret_val;
}
/**
* e1000_release_nvm_i210 - Release exclusive access to EEPROM
* @hw: pointer to the HW structure
*
* Stop any current commands to the EEPROM and clear the EEPROM request bit,
* then release the semaphores acquired.
**/
static void e1000_release_nvm_i210(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_release_nvm_i210");
e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
}
/**
* e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
* @hw: pointer to the HW structure
* @mask: specifies which semaphore to acquire
*
* Acquire the SW/FW semaphore to access the PHY or NVM. The mask
* will also specify which port we're acquiring the lock for.
**/
s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
{
u32 swfw_sync;
u32 swmask = mask;
u32 fwmask = mask << 16;
s32 ret_val = E1000_SUCCESS;
s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
DEBUGFUNC("e1000_acquire_swfw_sync_i210");
while (i < timeout) {
if (e1000_get_hw_semaphore_i210(hw)) {
ret_val = -E1000_ERR_SWFW_SYNC;
goto out;
}
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
if (!(swfw_sync & (fwmask | swmask)))
break;
/*
* Firmware currently using resource (fwmask)
* or other software thread using resource (swmask)
*/
e1000_put_hw_semaphore_generic(hw);
msec_delay_irq(5);
i++;
}
if (i == timeout) {
DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
ret_val = -E1000_ERR_SWFW_SYNC;
goto out;
}
swfw_sync |= swmask;
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
e1000_put_hw_semaphore_generic(hw);
out:
return ret_val;
}
/**
* e1000_release_swfw_sync_i210 - Release SW/FW semaphore
* @hw: pointer to the HW structure
* @mask: specifies which semaphore to acquire
*
* Release the SW/FW semaphore used to access the PHY or NVM. The mask
* will also specify which port we're releasing the lock for.
**/
void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
{
u32 swfw_sync;
DEBUGFUNC("e1000_release_swfw_sync_i210");
while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
; /* Empty */
swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
swfw_sync &= ~mask;
E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
e1000_put_hw_semaphore_generic(hw);
}
/**
* e1000_get_hw_semaphore_i210 - Acquire hardware semaphore
* @hw: pointer to the HW structure
*
* Acquire the HW semaphore to access the PHY or NVM
**/
static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw)
{
u32 swsm;
s32 timeout = hw->nvm.word_size + 1;
s32 i = 0;
DEBUGFUNC("e1000_get_hw_semaphore_i210");
/* Get the SW semaphore */
while (i < timeout) {
swsm = E1000_READ_REG(hw, E1000_SWSM);
if (!(swsm & E1000_SWSM_SMBI))
break;
usec_delay(50);
i++;
}
if (i == timeout) {
/* In rare circumstances, the SW semaphore may already be held
* unintentionally. Clear the semaphore once before giving up.
*/
if (hw->dev_spec._82575.clear_semaphore_once) {
hw->dev_spec._82575.clear_semaphore_once = false;
e1000_put_hw_semaphore_generic(hw);
for (i = 0; i < timeout; i++) {
swsm = E1000_READ_REG(hw, E1000_SWSM);
if (!(swsm & E1000_SWSM_SMBI))
break;
usec_delay(50);
}
}
/* If we do not have the semaphore here, we have to give up. */
if (i == timeout) {
DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
return -E1000_ERR_NVM;
}
}
/* Get the FW semaphore. */
for (i = 0; i < timeout; i++) {
swsm = E1000_READ_REG(hw, E1000_SWSM);
E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
/* Semaphore acquired if bit latched */
if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
break;
usec_delay(50);
}
if (i == timeout) {
/* Release semaphores */
e1000_put_hw_semaphore_generic(hw);
DEBUGOUT("Driver can't access the NVM\n");
return -E1000_ERR_NVM;
}
return E1000_SUCCESS;
}
/**
* e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the Shadow Ram to read
* @words: number of words to read
* @data: word read from the Shadow Ram
*
* Reads a 16 bit word from the Shadow Ram using the EERD register.
* Uses necessary synchronization semaphores.
**/
s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data)
{
s32 status = E1000_SUCCESS;
u16 i, count;
DEBUGFUNC("e1000_read_nvm_srrd_i210");
/* We cannot hold synchronization semaphores for too long,
* because of forceful takeover procedure. However it is more efficient
* to read in bursts than synchronizing access for each word. */
for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
E1000_EERD_EEWR_MAX_COUNT : (words - i);
if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
status = e1000_read_nvm_eerd(hw, offset, count,
data + i);
hw->nvm.ops.release(hw);
} else {
status = E1000_ERR_SWFW_SYNC;
}
if (status != E1000_SUCCESS)
break;
}
return status;
}
/**
* e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
* @hw: pointer to the HW structure
* @offset: offset within the Shadow RAM to be written to
* @words: number of words to write
* @data: 16 bit word(s) to be written to the Shadow RAM
*
* Writes data to Shadow RAM at offset using EEWR register.
*
* If e1000_update_nvm_checksum is not called after this function , the
* data will not be committed to FLASH and also Shadow RAM will most likely
* contain an invalid checksum.
*
* If error code is returned, data and Shadow RAM may be inconsistent - buffer
* partially written.
**/
s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data)
{
s32 status = E1000_SUCCESS;
u16 i, count;
DEBUGFUNC("e1000_write_nvm_srwr_i210");
/* We cannot hold synchronization semaphores for too long,
* because of forceful takeover procedure. However it is more efficient
* to write in bursts than synchronizing access for each word. */
for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
E1000_EERD_EEWR_MAX_COUNT : (words - i);
if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
status = e1000_write_nvm_srwr(hw, offset, count,
data + i);
hw->nvm.ops.release(hw);
} else {
status = E1000_ERR_SWFW_SYNC;
}
if (status != E1000_SUCCESS)
break;
}
return status;
}
/**
* e1000_write_nvm_srwr - Write to Shadow Ram using EEWR
* @hw: pointer to the HW structure
* @offset: offset within the Shadow Ram to be written to
* @words: number of words to write
* @data: 16 bit word(s) to be written to the Shadow Ram
*
* Writes data to Shadow Ram at offset using EEWR register.
*
* If e1000_update_nvm_checksum is not called after this function , the
* Shadow Ram will most likely contain an invalid checksum.
**/
static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data)
{
struct e1000_nvm_info *nvm = &hw->nvm;
u32 i, k, eewr = 0;
u32 attempts = 100000;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_nvm_srwr");
/*
* 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");
ret_val = -E1000_ERR_NVM;
goto out;
}
for (i = 0; i < words; i++) {
eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
(data[i] << E1000_NVM_RW_REG_DATA) |
E1000_NVM_RW_REG_START;
E1000_WRITE_REG(hw, E1000_SRWR, eewr);
for (k = 0; k < attempts; k++) {
if (E1000_NVM_RW_REG_DONE &
E1000_READ_REG(hw, E1000_SRWR)) {
ret_val = E1000_SUCCESS;
break;
}
usec_delay(5);
}
if (ret_val != E1000_SUCCESS) {
DEBUGOUT("Shadow RAM write EEWR timed out\n");
break;
}
}
out:
return ret_val;
}
/** e1000_read_invm_word_i210 - Reads OTP
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Reads 16-bit words from the OTP. Return error when the word is not
* stored in OTP.
**/
static s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
{
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u32 invm_dword;
u16 i;
u8 record_type, word_address;
DEBUGFUNC("e1000_read_invm_word_i210");
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
/* Get record type */
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
break;
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
if (word_address == address) {
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
DEBUGOUT2("Read INVM Word 0x%02x = %x",
address, *data);
status = E1000_SUCCESS;
break;
}
}
}
if (status != E1000_SUCCESS)
DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address);
return status;
}
/** e1000_read_invm_i210 - Read invm wrapper function for I210/I211
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Wrapper function to return data formerly found in the NVM.
**/
static s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset,
u16 E1000_UNUSEDARG words, u16 *data)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_invm_i210");
/* Only the MAC addr is required to be present in the iNVM */
switch (offset) {
case NVM_MAC_ADDR:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]);
ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1,
&data[1]);
ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2,
&data[2]);
if (ret_val != E1000_SUCCESS)
DEBUGOUT("MAC Addr not found in iNVM\n");
break;
case NVM_INIT_CTRL_2:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_2_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_INIT_CTRL_4:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_4_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_1_CFG:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_1_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_LED_0_2_CFG:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_0_2_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS;
}
break;
case NVM_ID_LED_SETTINGS:
ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) {
*data = ID_LED_RESERVED_FFFF;
ret_val = E1000_SUCCESS;
}
break;
case NVM_SUB_DEV_ID:
*data = hw->subsystem_device_id;
break;
case NVM_SUB_VEN_ID:
*data = hw->subsystem_vendor_id;
break;
case NVM_DEV_ID:
*data = hw->device_id;
break;
case NVM_VEN_ID:
*data = hw->vendor_id;
break;
default:
DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
*data = NVM_RESERVED_WORD;
break;
}
return ret_val;
}
/**
* e1000_read_invm_version - Reads iNVM version and image type
* @hw: pointer to the HW structure
* @invm_ver: version structure for the version read
*
* Reads iNVM version and image type.
**/
s32 e1000_read_invm_version(struct e1000_hw *hw,
struct e1000_fw_version *invm_ver)
{
u32 *record = NULL;
u32 *next_record = NULL;
u32 i = 0;
u32 invm_dword = 0;
u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
E1000_INVM_RECORD_SIZE_IN_BYTES);
u32 buffer[E1000_INVM_SIZE];
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u16 version = 0;
DEBUGFUNC("e1000_read_invm_version");
/* Read iNVM memory */
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i));
buffer[i] = invm_dword;
}
/* Read version number */
for (i = 1; i < invm_blocks; i++) {
record = &buffer[invm_blocks - i];
next_record = &buffer[invm_blocks - i + 1];
/* Check if we have first version location used */
if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
version = 0;
status = E1000_SUCCESS;
break;
}
/* Check if we have second version location used */
else if ((i == 1) &&
((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
status = E1000_SUCCESS;
break;
}
/*
* Check if we have odd version location
* used and it is the last one used
*/
else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
(i != 1))) {
version = (*next_record & E1000_INVM_VER_FIELD_TWO)
>> 13;
status = E1000_SUCCESS;
break;
}
/*
* Check if we have even version location
* used and it is the last one used
*/
else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
((*record & 0x3) == 0)) {
version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
status = E1000_SUCCESS;
break;
}
}
if (status == E1000_SUCCESS) {
invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
>> E1000_INVM_MAJOR_SHIFT;
invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
}
/* Read Image Type */
for (i = 1; i < invm_blocks; i++) {
record = &buffer[invm_blocks - i];
next_record = &buffer[invm_blocks - i + 1];
/* Check if we have image type in first location used */
if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
invm_ver->invm_img_type = 0;
status = E1000_SUCCESS;
break;
}
/* Check if we have image type in first location used */
else if ((((*record & 0x3) == 0) &&
((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
((((*record & 0x3) != 0) && (i != 1)))) {
invm_ver->invm_img_type =
(*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
status = E1000_SUCCESS;
break;
}
}
return status;
}
/**
* e1000_validate_nvm_checksum_i210 - 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_i210(struct e1000_hw *hw)
{
s32 status = E1000_SUCCESS;
s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
DEBUGFUNC("e1000_validate_nvm_checksum_i210");
if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
/*
* Replace the read function with semaphore grabbing with
* the one that skips this for a while.
* We have semaphore taken already here.
*/
read_op_ptr = hw->nvm.ops.read;
hw->nvm.ops.read = e1000_read_nvm_eerd;
status = e1000_validate_nvm_checksum_generic(hw);
/* Revert original read operation. */
hw->nvm.ops.read = read_op_ptr;
hw->nvm.ops.release(hw);
} else {
status = E1000_ERR_SWFW_SYNC;
}
return status;
}
/**
* e1000_update_nvm_checksum_i210 - 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. Next commit EEPROM data onto the Flash.
**/
s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 checksum = 0;
u16 i, nvm_data;
DEBUGFUNC("e1000_update_nvm_checksum_i210");
/*
* 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
*/
ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);
if (ret_val != E1000_SUCCESS) {
DEBUGOUT("EEPROM read failed\n");
goto out;
}
if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
/*
* Do not use hw->nvm.ops.write, hw->nvm.ops.read
* because we do not want to take the synchronization
* semaphores twice here.
*/
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);
if (ret_val) {
hw->nvm.ops.release(hw);
DEBUGOUT("NVM Read Error while updating checksum.\n");
goto out;
}
checksum += nvm_data;
}
checksum = (u16) NVM_SUM - checksum;
ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
&checksum);
if (ret_val != E1000_SUCCESS) {
hw->nvm.ops.release(hw);
DEBUGOUT("NVM Write Error while updating checksum.\n");
goto out;
}
hw->nvm.ops.release(hw);
ret_val = e1000_update_flash_i210(hw);
} else {
ret_val = E1000_ERR_SWFW_SYNC;
}
out:
return ret_val;
}
/**
* e1000_get_flash_presence_i210 - Check if flash device is detected.
* @hw: pointer to the HW structure
*
**/
bool e1000_get_flash_presence_i210(struct e1000_hw *hw)
{
u32 eec = 0;
bool ret_val = false;
DEBUGFUNC("e1000_get_flash_presence_i210");
eec = E1000_READ_REG(hw, E1000_EECD);
if (eec & E1000_EECD_FLASH_DETECTED_I210)
ret_val = true;
return ret_val;
}
/**
* e1000_update_flash_i210 - Commit EEPROM to the flash
* @hw: pointer to the HW structure
*
**/
s32 e1000_update_flash_i210(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u32 flup;
DEBUGFUNC("e1000_update_flash_i210");
ret_val = e1000_pool_flash_update_done_i210(hw);
if (ret_val == -E1000_ERR_NVM) {
DEBUGOUT("Flash update time out\n");
goto out;
}
flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210;
E1000_WRITE_REG(hw, E1000_EECD, flup);
ret_val = e1000_pool_flash_update_done_i210(hw);
if (ret_val == E1000_SUCCESS)
DEBUGOUT("Flash update complete\n");
else
DEBUGOUT("Flash update time out\n");
out:
return ret_val;
}
/**
* e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
* @hw: pointer to the HW structure
*
**/
s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_NVM;
u32 i, reg;
DEBUGFUNC("e1000_pool_flash_update_done_i210");
for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
reg = E1000_READ_REG(hw, E1000_EECD);
if (reg & E1000_EECD_FLUDONE_I210) {
ret_val = E1000_SUCCESS;
break;
}
usec_delay(5);
}
return ret_val;
}
/**
* e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers
* @hw: pointer to the HW structure
*
* Initialize the i210/i211 NVM parameters and function pointers.
**/
static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
struct e1000_nvm_info *nvm = &hw->nvm;
DEBUGFUNC("e1000_init_nvm_params_i210");
ret_val = e1000_init_nvm_params_82575(hw);
nvm->ops.acquire = e1000_acquire_nvm_i210;
nvm->ops.release = e1000_release_nvm_i210;
nvm->ops.valid_led_default = e1000_valid_led_default_i210;
if (e1000_get_flash_presence_i210(hw)) {
hw->nvm.type = e1000_nvm_flash_hw;
nvm->ops.read = e1000_read_nvm_srrd_i210;
nvm->ops.write = e1000_write_nvm_srwr_i210;
nvm->ops.validate = e1000_validate_nvm_checksum_i210;
nvm->ops.update = e1000_update_nvm_checksum_i210;
} else {
hw->nvm.type = e1000_nvm_invm;
nvm->ops.read = e1000_read_invm_i210;
nvm->ops.write = NULL;
nvm->ops.validate = NULL;
nvm->ops.update = NULL;
}
return ret_val;
}
/**
* e1000_init_function_pointers_i210 - Init func ptrs.
* @hw: pointer to the HW structure
*
* Called to initialize all function pointers and parameters.
**/
void e1000_init_function_pointers_i210(struct e1000_hw *hw)
{
e1000_init_function_pointers_82575(hw);
hw->nvm.ops.init_params = e1000_init_nvm_params_i210;
return;
}
/**
* e1000_valid_led_default_i210 - Verify a valid default LED config
* @hw: pointer to the HW structure
* @data: pointer to the NVM (EEPROM)
*
* Read the EEPROM for the current default LED configuration. If the
* LED configuration is not valid, set to a valid LED configuration.
**/
static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
{
s32 ret_val;
DEBUGFUNC("e1000_valid_led_default_i210");
ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
goto out;
}
if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
switch (hw->phy.media_type) {
case e1000_media_type_internal_serdes:
*data = ID_LED_DEFAULT_I210_SERDES;
break;
case e1000_media_type_copper:
default:
*data = ID_LED_DEFAULT_I210;
break;
}
}
out:
return ret_val;
}
/**
* __e1000_access_xmdio_reg - Read/write XMDIO register
* @hw: pointer to the HW structure
* @address: XMDIO address to program
* @dev_addr: device address to program
* @data: pointer to value to read/write from/to the XMDIO address
* @read: boolean flag to indicate read or write
**/
static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address,
u8 dev_addr, u16 *data, bool read)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("__e1000_access_xmdio_reg");
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
if (ret_val)
return ret_val;
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
if (ret_val)
return ret_val;
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
dev_addr);
if (ret_val)
return ret_val;
if (read)
ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
else
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
if (ret_val)
return ret_val;
/* Recalibrate the device back to 0 */
ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
if (ret_val)
return ret_val;
return ret_val;
}
/**
* e1000_read_xmdio_reg - Read XMDIO register
* @hw: pointer to the HW structure
* @addr: XMDIO address to program
* @dev_addr: device address to program
* @data: value to be read from the EMI address
**/
s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
{
DEBUGFUNC("e1000_read_xmdio_reg");
return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, true);
}
/**
* e1000_write_xmdio_reg - Write XMDIO register
* @hw: pointer to the HW structure
* @addr: XMDIO address to program
* @dev_addr: device address to program
* @data: value to be written to the XMDIO address
**/
s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
{
DEBUGFUNC("e1000_read_xmdio_reg");
return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, false);
}

View file

@ -0,0 +1,91 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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_I210_H_
#define _E1000_I210_H_
bool e1000_get_flash_presence_i210(struct e1000_hw *hw);
s32 e1000_update_flash_i210(struct e1000_hw *hw);
s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw);
s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw);
s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
s32 e1000_read_invm_version(struct e1000_hw *hw,
struct e1000_fw_version *invm_ver);
s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
u16 *data);
s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
u16 data);
#define E1000_STM_OPCODE 0xDB00
#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
(u8)((invm_dword) & 0x7)
#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
(u8)(((invm_dword) & 0x0000FE00) >> 9)
#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
(u16)(((invm_dword) & 0xFFFF0000) >> 16)
enum E1000_INVM_STRUCTURE_TYPE {
E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00,
E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01,
E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02,
E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03,
E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04,
E1000_INVM_INVALIDATED_STRUCTURE = 0x0F,
};
#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
#define E1000_INVM_ULT_BYTES_SIZE 8
#define E1000_INVM_RECORD_SIZE_IN_BYTES 4
#define E1000_INVM_VER_FIELD_ONE 0x1FF8
#define E1000_INVM_VER_FIELD_TWO 0x7FE000
#define E1000_INVM_IMGTYPE_FIELD 0x1F800000
#define E1000_INVM_MAJOR_MASK 0x3F0
#define E1000_INVM_MINOR_MASK 0xF
#define E1000_INVM_MAJOR_SHIFT 4
#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_OFF1_OFF2))
#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_OFF1_ON2))
/* NVM offset defaults for I211 devices */
#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243
#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1
#define NVM_LED_1_CFG_DEFAULT_I211 0x0184
#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -28,10 +28,6 @@
#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);
s32 e1000_blink_led_generic(struct e1000_hw *hw);
s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw);
@ -46,31 +42,28 @@ 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);
u16 *duplex);
s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
u16 *speed, u16 *duplex);
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);
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_validate_mdi_setting_crossover_generic(struct e1000_hw *hw);
s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
u32 offset, u8 data);
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_config_collision_dist_generic(struct e1000_hw *hw);
void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count);
void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value);
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);

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -27,8 +27,6 @@
#include "e1000_api.h"
static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
/**
* e1000_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
@ -37,10 +35,10 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
* Calculates the checksum for some buffer on a specified length. The
* checksum calculated is returned.
**/
static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
u8 e1000_calculate_checksum(u8 *buffer, u32 length)
{
u32 i;
u8 sum = 0;
u8 sum = 0;
DEBUGFUNC("e1000_calculate_checksum");
@ -66,17 +64,20 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
{
u32 hicr;
s32 ret_val = E1000_SUCCESS;
u8 i;
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) {
if (!(hicr & E1000_HICR_EN)) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
goto out;
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* check the previous command is completed */
for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
@ -88,12 +89,10 @@ s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
DEBUGOUT("Previous command timeout failed .\n");
ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
goto out;
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -105,18 +104,17 @@ out:
**/
bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
{
u32 fwsm;
u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
DEBUGFUNC("e1000_check_mng_mode_generic");
fwsm = E1000_READ_REG(hw, E1000_FWSM);
return (fwsm & E1000_FWSM_MODE_MASK) ==
(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
}
/**
* e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX
* 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
@ -129,102 +127,50 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
u32 offset;
s32 ret_val, hdr_csum, csum;
u8 i, len;
bool tx_filter = true;
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)) {
tx_filter = false;
goto out;
hw->mac.tx_pkt_filtering = false;
return hw->mac.tx_pkt_filtering;
}
/*
* If we can't read from the host interface for whatever
/* If we can't read from the host interface for whatever
* reason, disable filtering.
*/
ret_val = hw->mac.ops.mng_enable_host_if(hw);
ret_val = e1000_mng_enable_host_if_generic(hw);
if (ret_val != E1000_SUCCESS) {
tx_filter = false;
goto out;
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);
}
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
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)
goto out;
if (hdr->signature != E1000_IAMT_SIGNATURE)
goto out;
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))
tx_filter = false;
hw->mac.tx_pkt_filtering = false;
out:
hw->mac.tx_pkt_filtering = tx_filter;
return tx_filter;
}
/**
* 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)
goto out;
/* 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)
goto out;
/* Write the manageability command header */
ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
if (ret_val)
goto out;
/* 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);
out:
return ret_val;
return hw->mac.tx_pkt_filtering;
}
/**
@ -235,7 +181,7 @@ out:
* 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)
struct e1000_host_mng_command_header *hdr)
{
u16 i, length = sizeof(struct e1000_host_mng_command_header);
@ -249,7 +195,7 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
/* 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));
*((u32 *) hdr + i));
E1000_WRITE_FLUSH(hw);
}
@ -269,22 +215,19 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
* 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)
u16 length, u16 offset, u8 *sum)
{
u8 *tmp;
u8 *bufptr = buffer;
u32 data = 0;
s32 ret_val = E1000_SUCCESS;
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) {
ret_val = -E1000_ERR_PARAM;
goto out;
}
if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
return -E1000_ERR_PARAM;
tmp = (u8 *)&data;
prev_bytes = offset & 0x3;
@ -307,8 +250,7 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
/* Calculate length in DWORDs */
length >>= 2;
/*
* The device driver writes the relevant command block into the
/* The device driver writes the relevant command block into the
* ram area.
*/
for (i = 0; i < length; i++) {
@ -318,7 +260,7 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
data);
data);
}
if (remaining) {
for (j = 0; j < sizeof(u32); j++) {
@ -329,55 +271,286 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
*sum += *(tmp + j);
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
data);
}
out:
return ret_val;
return E1000_SUCCESS;
}
/**
* e1000_enable_mng_pass_thru - Enable processing of ARP's
* 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 = e1000_mng_enable_host_if_generic(hw);
if (ret_val)
return ret_val;
/* Populate the host interface with the contents of "buffer". */
ret_val = e1000_mng_host_if_write_generic(hw, buffer, length,
sizeof(hdr), &(hdr.checksum));
if (ret_val)
return ret_val;
/* Write the manageability command header */
ret_val = e1000_mng_write_cmd_header_generic(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 allow ARPs to be processed by the host.
* 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;
bool ret_val = false;
DEBUGFUNC("e1000_enable_mng_pass_thru");
if (!hw->mac.asf_firmware_present)
goto out;
return false;
manc = E1000_READ_REG(hw, E1000_MANC);
if (!(manc & E1000_MANC_RCV_TCO_EN) ||
!(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
goto out;
if (!(manc & E1000_MANC_RCV_TCO_EN))
return false;
if (hw->mac.arc_subsystem_valid) {
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))) {
ret_val = true;
goto out;
}
} else {
if ((manc & E1000_MANC_SMBUS_EN) &&
!(manc & E1000_MANC_ASF_EN)) {
ret_val = true;
goto out;
}
(e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
return true;
} else if ((manc & E1000_MANC_SMBUS_EN) &&
!(manc & E1000_MANC_ASF_EN)) {
return true;
}
out:
return ret_val;
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)) {
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;
}
/**
* e1000_load_firmware - Writes proxy FW code buffer to host interface
* and execute.
* @hw: pointer to the HW structure
* @buffer: contains a firmware to write
* @length: the byte length of the buffer, must be multiple of 4 bytes
*
* Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled
* in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND.
**/
s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length)
{
u32 hicr, hibba, fwsm, icr, i;
DEBUGFUNC("e1000_load_firmware");
if (hw->mac.type < e1000_i210) {
DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
return -E1000_ERR_CONFIG;
}
/* Check that the host interface is enabled. */
hicr = E1000_READ_REG(hw, E1000_HICR);
if (!(hicr & E1000_HICR_EN)) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
return -E1000_ERR_CONFIG;
}
if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) {
DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n");
return -E1000_ERR_CONFIG;
}
if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) {
DEBUGOUT("Buffer length failure.\n");
return -E1000_ERR_INVALID_ARGUMENT;
}
/* Clear notification from ROM-FW by reading ICR register */
icr = E1000_READ_REG(hw, E1000_ICR_V2);
/* Reset ROM-FW */
hicr = E1000_READ_REG(hw, E1000_HICR);
hicr |= E1000_HICR_FW_RESET_ENABLE;
E1000_WRITE_REG(hw, E1000_HICR, hicr);
hicr |= E1000_HICR_FW_RESET;
E1000_WRITE_REG(hw, E1000_HICR, hicr);
E1000_WRITE_FLUSH(hw);
/* Wait till MAC notifies about its readiness after ROM-FW reset */
for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) {
icr = E1000_READ_REG(hw, E1000_ICR_V2);
if (icr & E1000_ICR_MNG)
break;
msec_delay(1);
}
/* Check for timeout */
if (i == E1000_HI_COMMAND_TIMEOUT) {
DEBUGOUT("FW reset failed.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* Wait till MAC is ready to accept new FW code */
for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
fwsm = E1000_READ_REG(hw, E1000_FWSM);
if ((fwsm & E1000_FWSM_FW_VALID) &&
((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT ==
E1000_FWSM_HI_EN_ONLY_MODE))
break;
msec_delay(1);
}
/* Check for timeout */
if (i == E1000_HI_COMMAND_TIMEOUT) {
DEBUGOUT("FW reset failed.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* Calculate length in DWORDs */
length >>= 2;
/* The device driver writes the relevant FW code block
* into the ram area in DWORDs via 1kB ram addressing window.
*/
for (i = 0; i < length; i++) {
if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) {
/* Point to correct 1kB ram window */
hibba = E1000_HI_FW_BASE_ADDRESS +
((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) *
(i / E1000_HI_FW_BLOCK_DWORD_LENGTH));
E1000_WRITE_REG(hw, E1000_HIBBA, hibba);
}
E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
i % E1000_HI_FW_BLOCK_DWORD_LENGTH,
*((u32 *)buffer + i));
}
/* Setting this bit tells the ARC that a new FW is ready to execute. */
hicr = E1000_READ_REG(hw, E1000_HICR);
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 for successful FW start. */
if (i == E1000_HI_COMMAND_TIMEOUT) {
DEBUGOUT("New FW did not start within timeout period.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
return E1000_SUCCESS;
}

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -32,12 +32,15 @@ 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);
u16 length, u16 offset, u8 *sum);
s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
struct e1000_host_mng_command_header *hdr);
struct e1000_host_mng_command_header *hdr);
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
u8 *buffer, u16 length);
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);
s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length);
enum e1000_mng_mode {
e1000_mng_mode_none = 0,
@ -47,35 +50,40 @@ enum e1000_mng_mode {
e1000_mng_mode_host_if_only
};
#define E1000_FACTPS_MNGCG 0x20000000
#define E1000_FACTPS_MNGCG 0x20000000
#define E1000_FWSM_MODE_MASK 0xE
#define E1000_FWSM_MODE_SHIFT 1
#define E1000_FWSM_MODE_MASK 0xE
#define E1000_FWSM_MODE_SHIFT 1
#define E1000_FWSM_FW_VALID 0x00008000
#define E1000_FWSM_HI_EN_ONLY_MODE 0x4
#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_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_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 command limit */
#define E1000_HICR_EN 0x01 /* Enable bit - RO */
#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_HI_FW_BASE_ADDRESS 0x10000
#define E1000_HI_FW_MAX_LENGTH (64 * 1024) /* Num of bytes */
#define E1000_HI_FW_BLOCK_DWORD_LENGTH 256 /* Num of DWORDs per page */
#define E1000_HICR_MEMORY_BASE_EN 0x200 /* MB Enable bit - RO */
#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
#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
#define E1000_IAMT_SIGNATURE 0x544D4149
#endif

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -386,7 +386,7 @@ static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
* 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)
u16 vf_number)
{
s32 ret_val;
u16 i;
@ -429,7 +429,7 @@ out_no_write:
* 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)
u16 vf_number)
{
s32 ret_val;
u16 i;
@ -465,7 +465,10 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
if (hw->mac.type == e1000_82576) {
switch (hw->mac.type) {
case e1000_82576:
case e1000_i350:
case e1000_i354:
mbx->timeout = 0;
mbx->usec_delay = 0;
@ -484,8 +487,8 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
mbx->stats.reqs = 0;
mbx->stats.acks = 0;
mbx->stats.rsts = 0;
default:
return E1000_SUCCESS;
}
return E1000_SUCCESS;
}

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -30,49 +30,49 @@
#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_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_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_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
#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
*/
#define E1000_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with
* this are the ACK */
#define E1000_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with
* this are the NACK */
#define E1000_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still
clear to send requests */
#define E1000_VT_MSGINFO_SHIFT 16
/* bits 23:16 are used for exra info for certain messages */
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
/* 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_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 /* VF requests to set VMOLR.LPE */
#define E1000_VF_SET_PROMISC 0x06 /*VF requests 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_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_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 */
#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);

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -27,7 +27,6 @@
#include "e1000_api.h"
static void e1000_stop_nvm(struct e1000_hw *hw);
static void e1000_reload_nvm_generic(struct e1000_hw *hw);
/**
@ -170,7 +169,6 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
{
u32 attempts = 100000;
u32 i, reg = 0;
s32 ret_val = -E1000_ERR_NVM;
DEBUGFUNC("e1000_poll_eerd_eewr_done");
@ -180,15 +178,13 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg)
else
reg = E1000_READ_REG(hw, E1000_EEWR);
if (reg & E1000_NVM_RW_REG_DONE) {
ret_val = E1000_SUCCESS;
break;
}
if (reg & E1000_NVM_RW_REG_DONE)
return E1000_SUCCESS;
usec_delay(5);
}
return ret_val;
return -E1000_ERR_NVM;
}
/**
@ -203,7 +199,6 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
{
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_acquire_nvm_generic");
@ -222,10 +217,10 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw)
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, E1000_EECD, eecd);
DEBUGOUT("Could not acquire NVM grant\n");
ret_val = -E1000_ERR_NVM;
return -E1000_ERR_NVM;
}
return ret_val;
return E1000_SUCCESS;
}
/**
@ -303,28 +298,27 @@ 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);
s32 ret_val = E1000_SUCCESS;
u16 timeout = 0;
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);
timeout = NVM_MAX_RETRY_SPI;
/*
* Read "Status Register" repeatedly until the LSB is cleared.
/* 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);
hw->nvm.opcode_bits);
spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8);
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
break;
@ -336,12 +330,70 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
if (!timeout) {
DEBUGOUT("SPI NVM Status error\n");
ret_val = -E1000_ERR_NVM;
goto out;
return -E1000_ERR_NVM;
}
}
out:
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;
}
@ -362,15 +414,13 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
DEBUGFUNC("e1000_read_nvm_eerd");
/*
* A check for invalid values: offset too large, too many words,
/* 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");
ret_val = -E1000_ERR_NVM;
goto out;
return -E1000_ERR_NVM;
}
for (i = 0; i < words; i++) {
@ -383,10 +433,9 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
break;
data[i] = (E1000_READ_REG(hw, E1000_EERD) >>
E1000_NVM_RW_REG_DATA);
E1000_NVM_RW_REG_DATA);
}
out:
return ret_val;
}
@ -405,43 +454,42 @@ out:
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;
s32 ret_val = -E1000_ERR_NVM;
u16 widx = 0;
DEBUGFUNC("e1000_write_nvm_spi");
/*
* A check for invalid values: offset too large, too many words,
/* 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");
ret_val = -E1000_ERR_NVM;
goto out;
return -E1000_ERR_NVM;
}
ret_val = nvm->ops.acquire(hw);
if (ret_val)
goto out;
while (widx < words) {
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
ret_val = e1000_ready_nvm_eeprom(hw);
ret_val = nvm->ops.acquire(hw);
if (ret_val)
goto release;
return ret_val;
ret_val = e1000_ready_nvm_eeprom(hw);
if (ret_val) {
nvm->ops.release(hw);
return ret_val;
}
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);
nvm->opcode_bits);
e1000_standby_nvm(hw);
/*
* Some SPI eeproms use the 8th address bit embedded in the
/* Some SPI eeproms use the 8th address bit embedded in the
* opcode
*/
if ((nvm->address_bits == 8) && (offset >= 128))
@ -450,7 +498,7 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
/* 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);
nvm->address_bits);
/* Loop to allow for up to whole page write of eeprom */
while (widx < words) {
@ -464,49 +512,186 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
break;
}
}
msec_delay(10);
nvm->ops.release(hw);
}
msec_delay(10);
release:
nvm->ops.release(hw);
out:
return ret_val;
}
/**
* e1000_read_pba_num_generic - Read device part number
* 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_num_generic(struct e1000_hw *hw, u32 *pba_num)
s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size)
{
s32 ret_val;
s32 ret_val;
u16 nvm_data;
u16 pba_ptr;
u16 offset;
u16 length;
DEBUGFUNC("e1000_read_pba_num_generic");
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");
goto out;
return ret_val;
}
*pba_num = (u32)(nvm_data << 16);
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
goto out;
return ret_val;
}
*pba_num |= nvm_data;
out:
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");
/* make sure callers buffer is big enough to store the PBA */
if (pba_num_size < E1000_PBANUM_LENGTH) {
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 = E1000_PBANUM_LENGTH;
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
@ -545,7 +730,7 @@ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
**/
s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
s32 ret_val;
u16 checksum = 0;
u16 i, nvm_data;
@ -555,19 +740,17 @@ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
goto out;
return ret_val;
}
checksum += nvm_data;
}
if (checksum != (u16) NVM_SUM) {
DEBUGOUT("NVM Checksum Invalid\n");
ret_val = -E1000_ERR_NVM;
goto out;
return -E1000_ERR_NVM;
}
out:
return ret_val;
return E1000_SUCCESS;
}
/**
@ -580,7 +763,7 @@ out:
**/
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
{
s32 ret_val;
s32 ret_val;
u16 checksum = 0;
u16 i, nvm_data;
@ -590,7 +773,7 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error while updating checksum.\n");
goto out;
return ret_val;
}
checksum += nvm_data;
}
@ -599,7 +782,6 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw)
if (ret_val)
DEBUGOUT("NVM Write Error while updating checksum.\n");
out:
return ret_val;
}
@ -623,3 +805,110 @@ static void e1000_reload_nvm_generic(struct e1000_hw *hw)
E1000_WRITE_FLUSH(hw);
}
/**
* e1000_get_fw_version - Get firmware version information
* @hw: pointer to the HW structure
* @fw_vers: pointer to output version structure
*
* unsupported/not present features return 0 in version structure
**/
void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
{
u16 eeprom_verh, eeprom_verl, etrack_test, fw_version;
u8 q, hval, rem, result;
u16 comb_verh, comb_verl, comb_offset;
memset(fw_vers, 0, sizeof(struct e1000_fw_version));
/* basic eeprom version numbers, bits used vary by part and by tool
* used to create the nvm images */
/* Check which data format we have */
hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
switch (hw->mac.type) {
case e1000_i211:
e1000_read_invm_version(hw, fw_vers);
return;
case e1000_82575:
case e1000_82576:
case e1000_82580:
/* Use this format, unless EETRACK ID exists,
* then use alternate format
*/
if ((etrack_test & NVM_MAJOR_MASK) != NVM_ETRACK_VALID) {
hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
>> NVM_MAJOR_SHIFT;
fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK)
>> NVM_MINOR_SHIFT;
fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK);
goto etrack_id;
}
break;
case e1000_i210:
if (!(e1000_get_flash_presence_i210(hw))) {
e1000_read_invm_version(hw, fw_vers);
return;
}
/* fall through */
case e1000_i350:
case e1000_i354:
/* find combo image version */
hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
if ((comb_offset != 0x0) &&
(comb_offset != NVM_VER_INVALID)) {
hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
+ 1), 1, &comb_verh);
hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
1, &comb_verl);
/* get Option Rom version if it exists and is valid */
if ((comb_verh && comb_verl) &&
((comb_verh != NVM_VER_INVALID) &&
(comb_verl != NVM_VER_INVALID))) {
fw_vers->or_valid = true;
fw_vers->or_major =
comb_verl >> NVM_COMB_VER_SHFT;
fw_vers->or_build =
(comb_verl << NVM_COMB_VER_SHFT)
| (comb_verh >> NVM_COMB_VER_SHFT);
fw_vers->or_patch =
comb_verh & NVM_COMB_VER_MASK;
}
}
break;
default:
return;
}
hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
>> NVM_MAJOR_SHIFT;
/* check for old style version format in newer images*/
if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) {
eeprom_verl = (fw_version & NVM_COMB_VER_MASK);
} else {
eeprom_verl = (fw_version & NVM_MINOR_MASK)
>> NVM_MINOR_SHIFT;
}
/* Convert minor value to hex before assigning to output struct
* Val to be converted will not be higher than 99, per tool output
*/
q = eeprom_verl / NVM_HEX_CONV;
hval = q * NVM_HEX_TENS;
rem = eeprom_verl % NVM_HEX_CONV;
result = hval + rem;
fw_vers->eep_minor = result;
etrack_id:
if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) {
hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT)
| eeprom_verl;
}
return;
}

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -28,23 +28,44 @@
#ifndef _E1000_NVM_H_
#define _E1000_NVM_H_
struct e1000_fw_version {
u32 etrack_id;
u16 eep_major;
u16 eep_minor;
u16 eep_build;
u8 invm_major;
u8 invm_minor;
u8 invm_img_type;
bool or_valid;
u16 or_major;
u16 or_build;
u16 or_patch;
};
void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
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_num_generic(struct e1000_hw *hw, u32 *pba_num);
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);
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_eewr(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
u16 *data);
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
void e1000_release_nvm_generic(struct e1000_hw *hw);
void e1000_get_fw_version(struct e1000_hw *hw,
struct e1000_fw_version *fw_vers);
#define E1000_STM_OPCODE 0xDB00
#define E1000_STM_OPCODE 0xDB00
#endif

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -41,6 +41,7 @@
#include "kcompat.h"
#define usec_delay(x) udelay(x)
#define usec_delay_irq(x) udelay(x)
#ifndef msec_delay
#define msec_delay(x) do { \
/* Don't mdelay in interrupt context! */ \
@ -70,7 +71,11 @@
#define DEBUGOUT(S)
#define DEBUGOUT1(S, A...)
#ifdef DEBUG_FUNC
#define DEBUGFUNC(F) DEBUGOUT(F "\n")
#else
#define DEBUGFUNC(F)
#endif
#define DEBUGOUT2 DEBUGOUT1
#define DEBUGOUT3 DEBUGOUT2
#define DEBUGOUT7 DEBUGOUT3

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -28,7 +28,6 @@
#ifndef _E1000_PHY_H_
#define _E1000_PHY_H_
void e1000_init_phy_ops_generic(struct e1000_hw *hw);
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);
@ -36,161 +35,212 @@ 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);
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);
s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data);
s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
bool line_override);
bool e1000_is_mphy_ready(struct e1000_hw *hw);
#define E1000_MAX_PHY_ADDR 4
#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 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 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
/* GS40G - I210 PHY defines */
#define GS40G_PAGE_SELECT 0x16
#define GS40G_PAGE_SHIFT 16
#define GS40G_OFFSET_MASK 0xFFFF
#define GS40G_PAGE_2 0x20000
#define GS40G_MAC_REG2 0x15
#define GS40G_MAC_LB 0x4140
#define GS40G_MAC_SPEED_1G 0X0006
#define GS40G_COPPER_SPEC 0x0010
#define GS40G_CS_POWER_DOWN 0x0002
#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 */
#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
#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
#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
/* I82577 PHY Control 2 */
#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400
#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200
#define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200
#define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400
#define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600
/* I82577 PHY Diagnostics Status */
#define I82577_DSTATUS_CABLE_LENGTH 0x03FC
#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
#define I82577_DSTATUS_CABLE_LENGTH 0x03FC
#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
/* 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 E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
#define E1000_MPHY_DIS_ACCESS 0x80000000 /* disable_access bit */
#define E1000_MPHY_ENA_ACCESS 0x40000000 /* enable_access bit */
#define E1000_MPHY_BUSY 0x00010000 /* busy bit */
#define E1000_MPHY_ADDRESS_FNC_OVERRIDE 0x20000000 /* fnc_override bit */
#define E1000_MPHY_ADDRESS_MASK 0x0000FFFF /* address mask */
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
/* Enable flexible speed on link-up */
#define IGP01E1000_GMII_FLEX_SPD 0x0010
#define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
#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_PSCFR_SMART_SPEED 0x0080
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
#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_PSSR_POLARITY_REVERSED 0x0002
#define IGP01E1000_PSSR_MDIX 0x0800
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
#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 IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
#define IGP01E1000_PSSR_MDIX 0x0800
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
#define IGP02E1000_AGC_RANGE 15
#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 IGP03E1000_PHY_MISC_CTRL 0x1B
#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
#define IGP02E1000_AGC_RANGE 15
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
#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_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#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 */
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */
#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */
#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
/* IFE PHY Extended Status Control */
#define IFE_PESC_POLARITY_REVERSED 0x0100
#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
#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010
#define IFE_PSC_FORCE_POLARITY 0x0020
/* 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 */
#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 MDI/MDI-X, 0=disable */
#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

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -25,15 +25,13 @@
*******************************************************************************/
/* Linux PRO/1000 Ethernet Driver main header file */
#ifndef _IGB_H_
#define _IGB_H_
#ifdef IGB_LRO
#include <net/tcp.h>
#endif
#include <linux/kobject.h>
#ifdef __VMKLNX__
#define NODE_ADDRESS_SIZE 6
@ -52,12 +50,6 @@
#include <linux/ethtool.h>
#endif
#ifdef SIOCSHWTSTAMP
#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)
@ -67,33 +59,37 @@ struct igb_adapter;
#include <linux/dca.h>
#endif
#ifndef SIOCSHWTSTAMP
#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)
/* Disable Netqueue for 1G driver */
#if defined( __VMKLNX__)
#ifdef __VMKNETDDI_QUEUEOPS__
#undef __VMKNETDDI_QUEUEOPS__
#endif
#endif /* defined(__VMKLNX__) */
#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))
#ifdef HAVE_PTP_1588_CLOCK
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
#endif /* HAVE_PTP_1588_CLOCK */
/* 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
@ -102,6 +98,7 @@ struct igb_adapter;
/* 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
@ -113,7 +110,7 @@ struct igb_adapter;
#define IGB_MAX_ITR_USECS 8191 /* 120 irq/sec */
#define NON_Q_VECTORS 1
#define MAX_Q_VECTORS 8
#define MAX_Q_VECTORS 10
/* Transmit and receive queues */
#define IGB_MAX_RX_QUEUES 16
@ -121,10 +118,13 @@ struct igb_adapter;
#define IGB_MAX_VF_MC_ENTRIES 30
#define IGB_MAX_VF_FUNCTIONS 8
#define IGB_MAX_VFTA_ENTRIES 128
#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];
@ -136,11 +136,20 @@ struct vf_data_storage {
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;
#ifdef HAVE_VF_SPOOFCHK_CONFIGURE
bool spoofchk_enabled;
#endif
#endif
};
#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
@ -153,25 +162,33 @@ struct vf_data_storage {
* descriptors until either it has this many to write back, or the
* ITR timer expires.
*/
#define IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8)
#define IGB_RX_HTHRESH 8
#define IGB_RX_WTHRESH 1
#define IGB_TX_PTHRESH 8
#define IGB_TX_HTHRESH 1
#define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \
adapter->msix_entries) ? 1 : 16)
#define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8)
#define IGB_RX_HTHRESH 8
#define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
#define IGB_TX_HTHRESH 1
#define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \
adapter->msix_entries) ? 1 : 4)
/* 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_64 64 /* Used for packet split */
#define IGB_RXBUFFER_128 128 /* Used for packet split */
#define IGB_RXBUFFER_1024 1024
#define IGB_RXBUFFER_256 256
#define IGB_RXBUFFER_2048 2048
#define IGB_RXBUFFER_4096 4096
#define IGB_RXBUFFER_8192 8192
#define IGB_RXBUFFER_16384 16384
#define IGB_RX_HDR_LEN IGB_RXBUFFER_256
#if MAX_SKB_FRAGS < 8
#define IGB_RX_BUFSZ ALIGN(MAX_JUMBO_FRAME_SIZE / MAX_SKB_FRAGS, 1024)
#else
#define IGB_RX_BUFSZ IGB_RXBUFFER_2048
#endif
/* Packet Buffer allocations */
#define IGB_PBA_BYTES_SHIFT 0xA
@ -180,13 +197,11 @@ struct vf_data_storage {
#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 AUTO_ALL_MODES 0
#define IGB_EEPROM_APME 0x0400
#define AUTO_ALL_MODES 0
#ifndef IGB_MASTER_SLAVE
/* Switch to override PHY master/slave setting */
@ -195,68 +210,67 @@ struct vf_data_storage {
#define IGB_MNG_VLAN_NONE -1
#ifdef IGB_LRO
#define IGB_LRO_MAX 32 /*Maximum number of LRO descriptors*/
#define IGB_LRO_GLOBAL 10
struct igb_cb {
#ifdef HAVE_VLAN_RX_REGISTER
u16 vid; /* VLAN tag */
#endif
};
#define IGB_CB(skb) ((struct igb_cb *)(skb)->cb)
struct igb_lro_stats {
u32 flushed;
u32 coal;
u32 recycled;
enum igb_tx_flags {
/* cmd_type flags */
IGB_TX_FLAGS_VLAN = 0x01,
IGB_TX_FLAGS_TSO = 0x02,
IGB_TX_FLAGS_TSTAMP = 0x04,
/* olinfo flags */
IGB_TX_FLAGS_IPV4 = 0x10,
IGB_TX_FLAGS_CSUM = 0x20,
};
struct igb_lro_desc {
struct hlist_node lro_node;
struct sk_buff *skb;
u32 source_ip;
u32 dest_ip;
u16 source_port;
u16 dest_port;
u16 vlan_tag;
u16 len;
u32 next_seq;
u32 ack_seq;
u16 window;
u16 mss;
u16 opt_bytes;
u16 psh:1;
u32 tsval;
u32 tsecr;
u32 append_cnt;
};
/* VLAN info */
#define IGB_TX_FLAGS_VLAN_MASK 0xffff0000
#define IGB_TX_FLAGS_VLAN_SHIFT 16
struct igb_lro_list {
struct hlist_head active;
struct hlist_head free;
int active_cnt;
struct igb_lro_stats stats;
};
/*
* The largest size we can write to the descriptor is 65535. In order to
* maintain a power of two alignment we have to limit ourselves to 32K.
*/
#define IGB_MAX_TXD_PWR 15
#define IGB_MAX_DATA_PER_TXD (1 << IGB_MAX_TXD_PWR)
/* Tx Descriptors needed, worst case */
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD)
#ifndef MAX_SKB_FRAGS
#define DESC_NEEDED 4
#elif (MAX_SKB_FRAGS < 16)
#define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4)
#else
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
#endif
#endif /* IGB_LRO */
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
struct igb_buffer {
struct igb_tx_buffer {
union e1000_adv_tx_desc *next_to_watch;
unsigned long time_stamp;
struct sk_buff *skb;
dma_addr_t dma;
union {
/* TX */
struct {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
u16 mapped_as_page;
u16 gso_segs;
};
unsigned int bytecount;
u16 gso_segs;
__be16 protocol;
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
u32 tx_flags;
};
#ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT
/* RX */
struct {
unsigned long page_offset;
struct page *page;
dma_addr_t page_dma;
};
struct igb_rx_buffer {
dma_addr_t dma;
#ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT
struct sk_buff *skb;
#else
struct page *page;
u32 page_offset;
#endif
};
};
struct igb_tx_queue_stats {
@ -271,61 +285,64 @@ struct igb_rx_queue_stats {
u64 drops;
u64 csum_err;
u64 alloc_failed;
u64 ipv4_packets; /* IPv4 headers processed */
u64 ipv4e_packets; /* IPv4E headers with extensions processed */
u64 ipv6_packets; /* IPv6 headers processed */
u64 ipv6e_packets; /* IPv6E headers with extensions processed */
u64 tcp_packets; /* TCP headers processed */
u64 udp_packets; /* UDP headers processed */
u64 sctp_packets; /* SCTP headers processed */
u64 nfs_packets; /* NFS headers processe */
};
struct igb_q_vector {
struct igb_adapter *adapter; /* backlink */
struct igb_ring *rx_ring;
struct igb_ring *tx_ring;
struct napi_struct napi;
u32 eims_value;
u16 cpu;
u16 itr_val;
u8 set_itr;
void __iomem *itr_register;
#ifdef IGB_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
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_ring {
struct igb_q_vector *q_vector; /* backlink to q_vector */
struct net_device *netdev; /* back pointer to net_device */
struct pci_dev *pdev; /* pci device for dma mapping */
dma_addr_t dma; /* phys address of the ring */
void *desc; /* descriptor ring memory */
unsigned int size; /* length of desc. ring in bytes */
u16 count; /* number of desc. in the ring */
u16 next_to_use;
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;
};
#ifdef HAVE_PTP_1588_CLOCK
unsigned long last_rx_timestamp;
#endif /* HAVE_PTP_1588_CLOCK */
void *desc; /* descriptor ring memory */
unsigned long flags; /* ring specific flags */
void __iomem *tail; /* pointer to ring tail register */
dma_addr_t dma; /* phys address of the ring */
unsigned int size; /* length of desc. ring in bytes */
u16 count; /* number of desc. in the ring */
u8 queue_index; /* logical index of the ring*/
u8 reg_idx; /* physical index of the ring */
/* everything past this point are written often */
u16 next_to_clean;
u8 queue_index;
u8 reg_idx;
void __iomem *head;
void __iomem *tail;
struct igb_buffer *buffer_info; /* array of buffer info structs */
unsigned int total_bytes;
unsigned int total_packets;
u32 flags;
u16 next_to_use;
u16 next_to_alloc;
union {
/* TX */
struct {
struct igb_tx_queue_stats tx_stats;
bool detect_tx_hung;
};
/* RX */
struct {
struct igb_rx_queue_stats rx_stats;
u32 rx_buffer_len;
#ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT
u16 rx_buffer_len;
#else
struct sk_buff *skb;
#endif
#ifdef __VMKNETDDI_QUEUEOPS__
u8 mac_addr[NODE_ADDRESS_SIZE];
u8 active;
@ -333,89 +350,180 @@ struct igb_ring {
#endif
};
};
#ifdef CONFIG_IGB_VMDQ_NETDEV
struct net_device *vmdq_netdev;
int vqueue_index; /* queue index for virtual netdev */
#endif
} ____cacheline_internodealigned_in_smp;
struct igb_q_vector {
struct igb_adapter *adapter; /* backlink */
int cpu; /* CPU for DCA */
u32 eims_value; /* EIMS mask value */
u16 itr_val;
u8 set_itr;
void __iomem *itr_register;
struct igb_ring_container rx, tx;
struct napi_struct napi;
char name[IFNAMSIZ + 9];
#ifndef HAVE_NETDEV_NAPI_LIST
struct net_device poll_dev;
#endif
/* for dynamic allocation of rings associated with this q_vector */
struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
};
#define IGB_RING_FLAG_RX_CSUM 0x00000001 /* RX CSUM enabled */
#define IGB_RING_FLAG_RX_SCTP_CSUM 0x00000002 /* SCTP CSUM offload enabled */
#ifdef IGB_LRO
#define IGB_RING_FLAG_RX_LRO 0x00000004 /* LRO enabled */
#endif /* IGB_LRO */
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,
};
#define IGB_RING_FLAG_TX_CTX_IDX 0x00000001 /* HW requires context index */
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_ADVTXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
#define E1000_RX_DESC_ADV(R, i) \
(&(((union e1000_adv_rx_desc *)((R).desc))[i]))
#define E1000_TX_DESC_ADV(R, i) \
(&(((union e1000_adv_tx_desc *)((R).desc))[i]))
#define E1000_TX_CTXTDESC_ADV(R, i) \
(&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
#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 int igb_desc_unused(struct igb_ring *ring)
static inline u16 igb_desc_unused(const struct igb_ring *ring)
{
if (ring->next_to_clean > ring->next_to_use)
return ring->next_to_clean - ring->next_to_use - 1;
u16 ntc = ring->next_to_clean;
u16 ntu = ring->next_to_use;
return ring->count + ring->next_to_clean - ring->next_to_use - 1;
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 */
#ifdef IGB_HWMON
#define IGB_HWMON_TYPE_LOC 0
#define IGB_HWMON_TYPE_TEMP 1
#define IGB_HWMON_TYPE_CAUTION 2
#define IGB_HWMON_TYPE_MAX 3
struct hwmon_attr {
struct device_attribute dev_attr;
struct e1000_hw *hw;
struct e1000_thermal_diode_data *sensor;
char name[12];
};
struct hwmon_buff {
struct device *device;
struct hwmon_attr *hwmon_list;
unsigned int n_hwmon;
};
#endif /* IGB_HWMON */
/* board specific private data structure */
struct igb_adapter {
struct timer_list watchdog_timer;
struct timer_list phy_info_timer;
#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;
u16 tx_itr;
u16 rx_itr;
struct work_struct reset_task;
struct work_struct watchdog_task;
struct work_struct dma_err_task;
bool fc_autoneg;
u8 tx_timeout_factor;
#ifdef ETHTOOL_PHYS_ID
struct timer_list blink_timer;
unsigned long led_status;
#endif
/* TX */
struct igb_ring *tx_ring[IGB_MAX_TX_QUEUES];
unsigned long tx_queue_len;
u32 tx_timeout_count;
/* RX */
struct igb_ring *rx_ring[IGB_MAX_RX_QUEUES];
int num_tx_queues;
int num_rx_queues;
u32 max_frame_size;
u32 min_frame_size;
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
#ifndef HAVE_NETDEV_STATS_IN_NETDEV
struct net_device_stats net_stats;
#endif
#ifdef IGB_LRO
struct igb_lro_stats lro_stats;
#endif
#ifdef SIOCSHWTSTAMP
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;
@ -431,51 +539,170 @@ struct igb_adapter {
int msg_enable;
unsigned int num_q_vectors;
struct igb_q_vector *q_vector[MAX_Q_VECTORS];
struct msix_entry *msix_entries;
u32 eims_enable_mask;
u32 eims_other;
/* to not mess up cache alignment, always add to the bottom */
unsigned long state;
unsigned int flags;
u32 eeprom_wol;
u32 *config_space;
#ifdef HAVE_TX_MQ
struct igb_ring *multi_tx_table[IGB_MAX_TX_QUEUES];
#endif /* HAVE_TX_MQ */
u16 tx_ring_count;
u16 rx_ring_count;
#ifdef __VMKNETDDI_QUEUEOPS__
u32 n_rx_queues_allocated;
u32 n_tx_queues_allocated;
/* A place to salt away the RAR table before resetting the adapter
* during change MTU
*/
#endif
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;
char fw_version[32];
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_HWMON
struct hwmon_buff igb_hwmon_buff;
#else /* IGB_HWMON */
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];
bool old_lsc;
#endif /* IGB_HWMON */
u32 etrack_id;
#ifdef __VMKLNX__
u16 SmbTblLen;
u32 SmbTblAddr;
#endif /* __VMKLNX__ */
#ifdef HAVE_PTP_1588_CLOCK
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
struct delayed_work ptp_overflow_work;
struct work_struct ptp_tx_work;
struct sk_buff *ptp_tx_skb;
unsigned long ptp_tx_start;
unsigned long last_rx_ptp_check;
spinlock_t tmreg_lock;
struct cyclecounter cc;
struct timecounter tc;
u32 tx_hwtstamp_timeouts;
u32 rx_hwtstamp_cleared;
#endif /* HAVE_PTP_1588_CLOCK */
unsigned long link_check_timeout;
int devrc;
u16 eee_advert;
};
#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 << 3)
#define IGB_FLAG_LLI_PUSH (1 << 4)
#define IGB_FLAG_QUAD_PORT_A (1 << 5)
#define IGB_FLAG_QUEUE_PAIRS (1 << 6)
#define IGB_FLAG_HAS_MSI (1 << 0)
#define IGB_FLAG_DCA_ENABLED (1 << 1)
#define IGB_FLAG_LLI_PUSH (1 << 2)
#define IGB_FLAG_QUAD_PORT_A (1 << 3)
#define IGB_FLAG_QUEUE_PAIRS (1 << 4)
#define IGB_FLAG_EEE (1 << 5)
#define IGB_FLAG_DMAC (1 << 6)
#define IGB_FLAG_DETECT_BAD_DMA (1 << 7)
#define IGB_FLAG_PTP (1 << 8)
#define IGB_FLAG_RSS_FIELD_IPV4_UDP (1 << 9)
#define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 10)
#define IGB_FLAG_WOL_SUPPORTED (1 << 11)
#define IGB_FLAG_NEED_LINK_UPDATE (1 << 12)
#define IGB_FLAG_LOOPBACK_ENABLE (1 << 13)
#define IGB_FLAG_MEDIA_RESET (1 << 14)
#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;
};
#pragma pack(push,1)
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 */
};
#pragma pack(pop)
enum e1000_state_t {
__IGB_TESTING,
__IGB_RESETTING,
@ -498,17 +725,139 @@ 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_adv(struct sk_buff *, struct igb_ring *);
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_buffer *);
extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
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 HAVE_PTP_1588_CLOCK
extern void igb_ptp_init(struct igb_adapter *adapter);
extern void igb_ptp_stop(struct igb_adapter *adapter);
extern void igb_ptp_reset(struct igb_adapter *adapter);
extern void igb_ptp_tx_work(struct work_struct *work);
extern void igb_ptp_rx_hang(struct igb_adapter *adapter);
extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
struct sk_buff *skb);
extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
unsigned char *va,
struct sk_buff *skb);
static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
#ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT
igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb);
skb_pull(skb, IGB_TS_HDR_LEN);
#endif
return;
}
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS))
igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb);
/* Update the last_rx_timestamp timer in order to enable watchdog check
* for error case of latched timestamp on a dropped packet.
*/
rx_ring->last_rx_timestamp = jiffies;
}
extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd);
#endif /* HAVE_PTP_1588_CLOCK */
#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
#define E1000_PCS_CFG_IGN_SD 1
#ifdef IGB_HWMON
void igb_sysfs_exit(struct igb_adapter *adapter);
int igb_sysfs_init(struct igb_adapter *adapter);
#else
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_HWMON */
/* ESX igb CIM IOCTL definition */
#define SIOCINTELCIM 0x89F8
#define INTELCIM_ENUMDIAGS 0x01 /* enumerate diagnostics */
#define INTELCIM_RUNDIAG 0x02 /* run diagnostics */
#define INTELCIM_FNDSMB 0x03 /* Find SMBIOS entry and size */
#define INTELCIM_GETSMBTBL 0x04 /* get SMBIOS tables */
#define INTELCIM_WRITEMEM 0x05 /* write data from user space to memory */
#define INTELCIM_READMEM 0x06 /* read data from memory to user space */
#define INTELCIM_GET_PCIE_ERROR_INFO 0x07
#define INTELCIM_GET_PCI_LINK_STATUS 0x08
#define SM_ADDR_HIGH 0x000FFFFF
#define SM_ADDR_LOW 0x000F0000
static const unsigned char sm_anchor[4] = "_SM_";
struct smbios_table {
u8 AnchorString[4];
u8 EntryPointChecksum;
u8 EntryPointLength;
u8 SmMajorVersion;
u8 SmMinorVersion;
u16 MaxStructureSize;
u8 EntryPointRevision;
u8 FormattedArea[5];
u8 IntermediateAnchorString[5];
u8 IntermediateChecksum;
u16 TableLength;
u32 TableAddress;
u16 NumberSmStructures;
u8 SmBcdRevision;
} __attribute__((__packed__));
struct intelcim_mem_buf {
u64 addr;
u32 len; /* Length in bytes */
u8 data[0];
} __attribute__((__packed__));
struct intelcim_pcie_error_info
{
u32 num_regs; /* Number of dwords */
u32 data[0];
} __attribute__((__packed__));
struct igb_intelcim_ioctl_req {
u32 cmd;
union {
struct ethtool_gstrings gstrings;
struct ethtool_test test;
struct smbios_table tbl;
u8 smbios[0];
struct intelcim_mem_buf buf;
struct intelcim_pcie_error_info info;
u16 link_status;
} cmd_req;
} __attribute__((packed));
int igb_intelcim_ioctl(struct net_device *netdev, struct ifreq *ifr);
#endif /* _IGB_H_ */

View file

@ -0,0 +1,29 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,242 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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_HWMON
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/hwmon.h>
#include <linux/pci.h>
/* hwmon callback functions */
static ssize_t igb_hwmon_show_location(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
dev_attr);
return sprintf(buf, "loc%u\n",
igb_attr->sensor->location);
}
static ssize_t igb_hwmon_show_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
dev_attr);
unsigned int value;
/* reset the temp field */
igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw);
value = igb_attr->sensor->temp;
/* display millidegree */
value *= 1000;
return sprintf(buf, "%u\n", value);
}
static ssize_t igb_hwmon_show_cautionthresh(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
dev_attr);
unsigned int value = igb_attr->sensor->caution_thresh;
/* display millidegree */
value *= 1000;
return sprintf(buf, "%u\n", value);
}
static ssize_t igb_hwmon_show_maxopthresh(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
dev_attr);
unsigned int value = igb_attr->sensor->max_op_thresh;
/* display millidegree */
value *= 1000;
return sprintf(buf, "%u\n", value);
}
/* igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
* @ adapter: pointer to the adapter structure
* @ offset: offset in the eeprom sensor data table
* @ type: type of sensor data to display
*
* For each file we want in hwmon's sysfs interface we need a device_attribute
* This is included in our hwmon_attr struct that contains the references to
* the data structures we need to get the data to display.
*/
static int igb_add_hwmon_attr(struct igb_adapter *adapter,
unsigned int offset, int type) {
int rc;
unsigned int n_attr;
struct hwmon_attr *igb_attr;
n_attr = adapter->igb_hwmon_buff.n_hwmon;
igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr];
switch (type) {
case IGB_HWMON_TYPE_LOC:
igb_attr->dev_attr.show = igb_hwmon_show_location;
snprintf(igb_attr->name, sizeof(igb_attr->name),
"temp%u_label", offset);
break;
case IGB_HWMON_TYPE_TEMP:
igb_attr->dev_attr.show = igb_hwmon_show_temp;
snprintf(igb_attr->name, sizeof(igb_attr->name),
"temp%u_input", offset);
break;
case IGB_HWMON_TYPE_CAUTION:
igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh;
snprintf(igb_attr->name, sizeof(igb_attr->name),
"temp%u_max", offset);
break;
case IGB_HWMON_TYPE_MAX:
igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh;
snprintf(igb_attr->name, sizeof(igb_attr->name),
"temp%u_crit", offset);
break;
default:
rc = -EPERM;
return rc;
}
/* These always the same regardless of type */
igb_attr->sensor =
&adapter->hw.mac.thermal_sensor_data.sensor[offset];
igb_attr->hw = &adapter->hw;
igb_attr->dev_attr.store = NULL;
igb_attr->dev_attr.attr.mode = S_IRUGO;
igb_attr->dev_attr.attr.name = igb_attr->name;
sysfs_attr_init(&igb_attr->dev_attr.attr);
rc = device_create_file(&adapter->pdev->dev,
&igb_attr->dev_attr);
if (rc == 0)
++adapter->igb_hwmon_buff.n_hwmon;
return rc;
}
static void igb_sysfs_del_adapter(struct igb_adapter *adapter)
{
int i;
if (adapter == NULL)
return;
for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) {
device_remove_file(&adapter->pdev->dev,
&adapter->igb_hwmon_buff.hwmon_list[i].dev_attr);
}
kfree(adapter->igb_hwmon_buff.hwmon_list);
if (adapter->igb_hwmon_buff.device)
hwmon_device_unregister(adapter->igb_hwmon_buff.device);
}
/* called from igb_main.c */
void igb_sysfs_exit(struct igb_adapter *adapter)
{
igb_sysfs_del_adapter(adapter);
}
/* called from igb_main.c */
int igb_sysfs_init(struct igb_adapter *adapter)
{
struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff;
unsigned int i;
int n_attrs;
int rc = 0;
/* If this method isn't defined we don't support thermals */
if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
goto exit;
/* Don't create thermal hwmon interface if no sensors present */
rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw));
if (rc)
goto exit;
/* Allocation space for max attributes
* max num sensors * values (loc, temp, max, caution)
*/
n_attrs = E1000_MAX_SENSORS * 4;
igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr),
GFP_KERNEL);
if (!igb_hwmon->hwmon_list) {
rc = -ENOMEM;
goto err;
}
igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev);
if (IS_ERR(igb_hwmon->device)) {
rc = PTR_ERR(igb_hwmon->device);
goto err;
}
for (i = 0; i < E1000_MAX_SENSORS; i++) {
/* Only create hwmon sysfs entries for sensors that have
* meaningful data.
*/
if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
continue;
/* Bail if any hwmon attr struct fails to initialize */
rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION);
rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
if (rc)
goto err;
}
goto exit;
err:
igb_sysfs_del_adapter(adapter);
exit:
return rc;
}
#endif /* IGB_HWMON */

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -39,6 +39,7 @@
#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
@ -58,12 +59,12 @@
*/
#define IGB_PARAM(X, desc) \
static const int __devinitdata X[IGB_MAX_NIC+1] = IGB_PARAM_INIT; \
static const int 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 int 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);
@ -73,11 +74,12 @@
*
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
*/
IGB_PARAM(InterruptThrottleRate,
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 120 */
#define MIN_ITR 0
/* IntMode (Interrupt Mode)
*
* Valid Range: 0 - 2
@ -88,6 +90,8 @@ 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
@ -124,18 +128,17 @@ IGB_PARAM(LLISize, "Low Latency Interrupt on Packet Size (0-1500), default 0=off
#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");
IGB_PARAM(RSS, "Number of Receive-Side Scaling Descriptor Queues (0-8), default 1, 0=number of cpus");
#define DEFAULT_RSS 1
#define MAX_RSS ((adapter->hw.mac.type == e1000_82575) ? 4 : 8)
#define MIN_RSS 0
#define MAX_RSS 8
#define MIN_RSS 0
/* VMDQ (Enable VMDq multiqueue receive)
*
@ -143,12 +146,37 @@ IGB_PARAM(RSS, "Number of Receive-Side Scaling Descriptor Queues (0-8), default
*
* Default Value: 0
*/
IGB_PARAM(VMDQ, "Number of Virtual Machine Device Queues (0-8), default 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
#ifndef __VMKLNX__
/* 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
#endif /* __VMKLNX__ */
/* 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)
*
@ -156,12 +184,33 @@ IGB_PARAM(VMDQ, "Number of Virtual Machine Device Queues (0-8), default 0");
*
* Default Value: 1
*/
IGB_PARAM(QueuePairs, "Enable TX/RX queue pairs for interrupt handling (0,1), default 1=on");
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))");
struct igb_opt_list {
int i;
char *str;
};
struct igb_option {
enum { enable_option, range_option, list_option } type;
const char *name;
@ -174,14 +223,14 @@ struct igb_option {
} r;
struct { /* list_option info */
int nr;
struct igb_opt_list { int i; char *str; } *p;
struct igb_opt_list *p;
} l;
} arg;
};
static int __devinit igb_validate_option(unsigned int *value,
struct igb_option *opt,
struct igb_adapter *adapter)
static int igb_validate_option(unsigned int *value,
struct igb_option *opt,
struct igb_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@ -240,9 +289,10 @@ static int __devinit igb_validate_option(unsigned int *value,
* in a variable in the adapter structure.
**/
void __devinit igb_check_options(struct igb_adapter *adapter)
void 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,
@ -272,6 +322,9 @@ void __devinit igb_check_options(struct igb_adapter *adapter)
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",
@ -403,19 +456,58 @@ void __devinit igb_check_options(struct igb_adapter *adapter)
}
#endif
}
#ifndef __VMKLNX__
{ /* 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:
case e1000_i210:
case e1000_i211:
case e1000_i354:
adapter->vfs_allocated_count = 0;
DPRINTK(PROBE, INFO, "SR-IOV option max_vfs not supported.\n");
default:
break;
}
}
}
#endif /* __VMKLNX__ */
{ /* VMDQ - Enable VMDq multiqueue receive */
struct igb_option opt = {
.type = range_option,
.name = "VMDQ - VMDq multiqueue receive count",
.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) } }
};
if ((hw->mac.type != e1000_i210) ||
(hw->mac.type != e1000_i211)) {
#ifdef module_param_array
if (num_VMDQ > bd) {
#endif
adapter->vmdq_pools = VMDQ[bd];
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;
@ -425,11 +517,26 @@ void __devinit igb_check_options(struct igb_adapter *adapter)
#ifdef module_param_array
} else {
if (!adapter->vfs_allocated_count)
adapter->vmdq_pools = opt.def;
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
if (adapter->vmdq_pools) {
DPRINTK(PROBE, INFO, "VMDq not supported on ESX-5.5\n");
adapter->vmdq_pools = 0;
}
} else {
DPRINTK(PROBE, INFO, "VMDq option is not supported.\n");
adapter->vmdq_pools = opt.def;
}
}
{ /* RSS - Enable RSS multiqueue receives */
struct igb_option opt = {
@ -441,22 +548,48 @@ void __devinit igb_check_options(struct igb_adapter *adapter)
.max = MAX_RSS } }
};
if (adapter->vmdq_pools) {
switch (adapter->hw.mac.type) {
#ifndef __VMKLNX__
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:
#ifndef CONFIG_IGB_VMDQ_NETDEV
if (!!adapter->vmdq_pools) {
if (adapter->vmdq_pools <= 2) {
if (adapter->vmdq_pools == 2)
opt.arg.r.max = 3;
} else {
opt.arg.r.max = 1;
}
} else {
opt.arg.r.max = 4;
}
#else
opt.arg.r.max = !!adapter->vmdq_pools ? 1 : 4;
#endif /* CONFIG_IGB_VMDQ_NETDEV */
break;
case e1000_i210:
opt.arg.r.max = 4;
break;
case e1000_i211:
opt.arg.r.max = 2;
break;
case e1000_82576:
#ifndef CONFIG_IGB_VMDQ_NETDEV
if (!!adapter->vmdq_pools)
opt.arg.r.max = 2;
break;
#endif /* CONFIG_IGB_VMDQ_NETDEV */
case e1000_82580:
case e1000_i350:
case e1000_i354:
default:
if (!!adapter->vmdq_pools)
opt.arg.r.max = 1;
break;
}
if (adapter->int_mode != IGB_INT_MODE_MSIX) {
DPRINTK(PROBE, INFO, "RSS is not supported when in MSI/Legacy Interrupt mode, %s\n",
opt.err);
opt.arg.r.max = 1;
}
#ifdef module_param_array
@ -480,42 +613,195 @@ void __devinit igb_check_options(struct igb_adapter *adapter)
}
#endif
}
{ /* QueuePairs - Enable TX/RX queue pairs for interrupt handling */
{ /* 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",
.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.
* We must enable queue pairs if the number of queues
* exceeds the number of available interrupts. We are
* limited to 10, or 3 per unallocated vf. On I210 and
* I211 devices, we are limited to 5 interrupts.
* However, since I211 only supports 2 queues, we do not
* need to check and override the user option.
*/
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) {
if (qp == OPTION_DISABLED) {
if (adapter->rss_queues > 4)
qp = OPTION_ENABLED;
DPRINTK(PROBE, INFO,
"Number of queues exceeds available interrupts, %s\n",opt.err);
}
if (adapter->vmdq_pools > 4)
qp = OPTION_ENABLED;
if (adapter->rss_queues > 1 &&
(adapter->vmdq_pools > 3 ||
adapter->vfs_allocated_count > 6))
qp = OPTION_ENABLED;
if (hw->mac.type == e1000_i210 &&
adapter->rss_queues > 2)
qp = OPTION_ENABLED;
if (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 __VMKLNX__
{ /* 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
}
#endif /* __VMKLNX__ */
}

View file

@ -0,0 +1,962 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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"
#ifndef IGB_HWMON
#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;
#ifdef __VMKLNX__
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 */
}
#endif /* __VMKLNX__ */
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;
}
#ifdef __VMKLNX__
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, "0x%08x\n", adapter->etrack_id);
}
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;
if (adapter->old_lsc != hw->mac.get_link_status) {
bitmask |= 4;
adapter->old_lsc = hw->mac.get_link_status;
}
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_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);
}
#endif /* __VMKLNX__ */
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%02X%02X%02X%02X%02X%02X\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%02X%02X%02X%02X%02X%02X\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_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_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[] = {
{"numeports", &igb_numeports},
{"porttype", &igb_porttype},
{"macburn", &igb_macburn},
{"macadmn", &igb_macadmn},
#ifdef __VMKLNX__
{"fwbanner", &igb_fwbanner},
{"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},
{"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},
#endif /* __VMKLNX__ */
{"", 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)
{
#ifdef __VMKLNX__
igb_top_dir = proc_mkdir("driver/igb", NULL);
#else
igb_top_dir = proc_mkdir("driver/igb", NULL);
#endif /* __VMKLNX__ */
if (igb_top_dir == NULL)
return (-ENOMEM);
return 0;
}
void igb_procfs_topdir_exit(void)
{
#ifdef __VMKLNX__
remove_proc_entry("driver/igb", NULL);
#else
remove_proc_entry("driver/igb", NULL);
#endif /* __VMKLNX__ */
}
/* 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_HWMON */

View file

@ -0,0 +1,944 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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
*******************************************************************************/
/******************************************************************************
Copyright(c) 2011 Richard Cochran <richardcochran@gmail.com> for some of the
82576 and 82580 code
******************************************************************************/
#include "igb.h"
#include <linux/module.h>
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/ptp_classify.h>
#define INCVALUE_MASK 0x7fffffff
#define ISGN 0x80000000
/*
* The 82580 timesync updates the system timer every 8ns by 8ns,
* and this update value cannot be reprogrammed.
*
* Neither the 82576 nor the 82580 offer registers wide enough to hold
* nanoseconds time values for very long. For the 82580, SYSTIM always
* counts nanoseconds, but the upper 24 bits are not availible. The
* frequency is adjusted by changing the 32 bit fractional nanoseconds
* register, TIMINCA.
*
* For the 82576, the SYSTIM register time unit is affect by the
* choice of the 24 bit TININCA:IV (incvalue) field. Five bits of this
* field are needed to provide the nominal 16 nanosecond period,
* leaving 19 bits for fractional nanoseconds.
*
* We scale the NIC clock cycle by a large factor so that relatively
* small clock corrections can be added or subtracted at each clock
* tick. The drawbacks of a large factor are a) that the clock
* register overflows more quickly (not such a big deal) and b) that
* the increment per tick has to fit into 24 bits. As a result we
* need to use a shift of 19 so we can fit a value of 16 into the
* TIMINCA register.
*
*
* SYSTIMH SYSTIML
* +--------------+ +---+---+------+
* 82576 | 32 | | 8 | 5 | 19 |
* +--------------+ +---+---+------+
* \________ 45 bits _______/ fract
*
* +----------+---+ +--------------+
* 82580 | 24 | 8 | | 32 |
* +----------+---+ +--------------+
* reserved \______ 40 bits _____/
*
*
* The 45 bit 82576 SYSTIM overflows every
* 2^45 * 10^-9 / 3600 = 9.77 hours.
*
* The 40 bit 82580 SYSTIM overflows every
* 2^40 * 10^-9 / 60 = 18.3 minutes.
*/
#define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9)
#define IGB_PTP_TX_TIMEOUT (HZ * 15)
#define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT)
#define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1)
#define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT)
#define IGB_NBITS_82580 40
/*
* SYSTIM read access for the 82576
*/
static cycle_t igb_ptp_read_82576(const struct cyclecounter *cc)
{
struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
struct e1000_hw *hw = &igb->hw;
u64 val;
u32 lo, hi;
lo = E1000_READ_REG(hw, E1000_SYSTIML);
hi = E1000_READ_REG(hw, E1000_SYSTIMH);
val = ((u64) hi) << 32;
val |= lo;
return val;
}
/*
* SYSTIM read access for the 82580
*/
static cycle_t igb_ptp_read_82580(const struct cyclecounter *cc)
{
struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
struct e1000_hw *hw = &igb->hw;
u64 val;
u32 lo, hi;
/* The timestamp latches on lowest register read. For the 82580
* the lowest register is SYSTIMR instead of SYSTIML. However we only
* need to provide nanosecond resolution, so we just ignore it.
*/
E1000_READ_REG(hw, E1000_SYSTIMR);
lo = E1000_READ_REG(hw, E1000_SYSTIML);
hi = E1000_READ_REG(hw, E1000_SYSTIMH);
val = ((u64) hi) << 32;
val |= lo;
return val;
}
/*
* SYSTIM read access for I210/I211
*/
static void igb_ptp_read_i210(struct igb_adapter *adapter, struct timespec *ts)
{
struct e1000_hw *hw = &adapter->hw;
u32 sec, nsec;
/* The timestamp latches on lowest register read. For I210/I211, the
* lowest register is SYSTIMR. Since we only need to provide nanosecond
* resolution, we can ignore it.
*/
E1000_READ_REG(hw, E1000_SYSTIMR);
nsec = E1000_READ_REG(hw, E1000_SYSTIML);
sec = E1000_READ_REG(hw, E1000_SYSTIMH);
ts->tv_sec = sec;
ts->tv_nsec = nsec;
}
static void igb_ptp_write_i210(struct igb_adapter *adapter,
const struct timespec *ts)
{
struct e1000_hw *hw = &adapter->hw;
/*
* Writing the SYSTIMR register is not necessary as it only provides
* sub-nanosecond resolution.
*/
E1000_WRITE_REG(hw, E1000_SYSTIML, ts->tv_nsec);
E1000_WRITE_REG(hw, E1000_SYSTIMH, ts->tv_sec);
}
/**
* igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp
* @adapter: board private structure
* @hwtstamps: timestamp structure to update
* @systim: unsigned 64bit system time value.
*
* We need to convert the system time value stored in the RX/TXSTMP registers
* into a hwtstamp which can be used by the upper level timestamping functions.
*
* The 'tmreg_lock' spinlock is used to protect the consistency of the
* system time value. This is needed because reading the 64 bit time
* value involves reading two (or three) 32 bit registers. The first
* read latches the value. Ditto for writing.
*
* In addition, here have extended the system time with an overflow
* counter in software.
**/
static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter,
struct skb_shared_hwtstamps *hwtstamps,
u64 systim)
{
unsigned long flags;
u64 ns;
switch (adapter->hw.mac.type) {
case e1000_82576:
case e1000_82580:
case e1000_i350:
case e1000_i354:
spin_lock_irqsave(&adapter->tmreg_lock, flags);
ns = timecounter_cyc2time(&adapter->tc, systim);
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
memset(hwtstamps, 0, sizeof(*hwtstamps));
hwtstamps->hwtstamp = ns_to_ktime(ns);
break;
case e1000_i210:
case e1000_i211:
memset(hwtstamps, 0, sizeof(*hwtstamps));
/* Upper 32 bits contain s, lower 32 bits contain ns. */
hwtstamps->hwtstamp = ktime_set(systim >> 32,
systim & 0xFFFFFFFF);
break;
default:
break;
}
}
/*
* PTP clock operations
*/
static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
struct e1000_hw *hw = &igb->hw;
int neg_adj = 0;
u64 rate;
u32 incvalue;
if (ppb < 0) {
neg_adj = 1;
ppb = -ppb;
}
rate = ppb;
rate <<= 14;
rate = div_u64(rate, 1953125);
incvalue = 16 << IGB_82576_TSYNC_SHIFT;
if (neg_adj)
incvalue -= rate;
else
incvalue += rate;
E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | (incvalue & INCVALUE_82576_MASK));
return 0;
}
static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
struct e1000_hw *hw = &igb->hw;
int neg_adj = 0;
u64 rate;
u32 inca;
if (ppb < 0) {
neg_adj = 1;
ppb = -ppb;
}
rate = ppb;
rate <<= 26;
rate = div_u64(rate, 1953125);
/* At 2.5G speeds, the TIMINCA register on I354 updates the clock 2.5x
* as quickly. Account for this by dividing the adjustment by 2.5.
*/
if (hw->mac.type == e1000_i354) {
u32 status = E1000_READ_REG(hw, E1000_STATUS);
if ((status & E1000_STATUS_2P5_SKU) &&
!(status & E1000_STATUS_2P5_SKU_OVER)) {
rate <<= 1;
rate = div_u64(rate, 5);
}
}
inca = rate & INCVALUE_MASK;
if (neg_adj)
inca |= ISGN;
E1000_WRITE_REG(hw, E1000_TIMINCA, inca);
return 0;
}
static int igb_ptp_adjtime_82576(struct ptp_clock_info *ptp, s64 delta)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
unsigned long flags;
s64 now;
spin_lock_irqsave(&igb->tmreg_lock, flags);
now = timecounter_read(&igb->tc);
now += delta;
timecounter_init(&igb->tc, &igb->cc, now);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
return 0;
}
static int igb_ptp_adjtime_i210(struct ptp_clock_info *ptp, s64 delta)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
unsigned long flags;
struct timespec now, then = ns_to_timespec(delta);
spin_lock_irqsave(&igb->tmreg_lock, flags);
igb_ptp_read_i210(igb, &now);
now = timespec_add(now, then);
igb_ptp_write_i210(igb, (const struct timespec *)&now);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
return 0;
}
static int igb_ptp_gettime_82576(struct ptp_clock_info *ptp,
struct timespec *ts)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
unsigned long flags;
u64 ns;
u32 remainder;
spin_lock_irqsave(&igb->tmreg_lock, flags);
ns = timecounter_read(&igb->tc);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
ts->tv_nsec = remainder;
return 0;
}
static int igb_ptp_gettime_i210(struct ptp_clock_info *ptp,
struct timespec *ts)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
unsigned long flags;
spin_lock_irqsave(&igb->tmreg_lock, flags);
igb_ptp_read_i210(igb, ts);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
return 0;
}
static int igb_ptp_settime_82576(struct ptp_clock_info *ptp,
const struct timespec *ts)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
unsigned long flags;
u64 ns;
ns = ts->tv_sec * 1000000000ULL;
ns += ts->tv_nsec;
spin_lock_irqsave(&igb->tmreg_lock, flags);
timecounter_init(&igb->tc, &igb->cc, ns);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
return 0;
}
static int igb_ptp_settime_i210(struct ptp_clock_info *ptp,
const struct timespec *ts)
{
struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
ptp_caps);
unsigned long flags;
spin_lock_irqsave(&igb->tmreg_lock, flags);
igb_ptp_write_i210(igb, ts);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
return 0;
}
static int igb_ptp_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
return -EOPNOTSUPP;
}
/**
* igb_ptp_tx_work
* @work: pointer to work struct
*
* This work function polls the TSYNCTXCTL valid bit to determine when a
* timestamp has been taken for the current stored skb.
*/
void igb_ptp_tx_work(struct work_struct *work)
{
struct igb_adapter *adapter = container_of(work, struct igb_adapter,
ptp_tx_work);
struct e1000_hw *hw = &adapter->hw;
u32 tsynctxctl;
if (!adapter->ptp_tx_skb)
return;
if (time_is_before_jiffies(adapter->ptp_tx_start +
IGB_PTP_TX_TIMEOUT)) {
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
adapter->tx_hwtstamp_timeouts++;
dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang");
return;
}
tsynctxctl = E1000_READ_REG(hw, E1000_TSYNCTXCTL);
if (tsynctxctl & E1000_TSYNCTXCTL_VALID)
igb_ptp_tx_hwtstamp(adapter);
else
/* reschedule to check later */
schedule_work(&adapter->ptp_tx_work);
}
static void igb_ptp_overflow_check(struct work_struct *work)
{
struct igb_adapter *igb =
container_of(work, struct igb_adapter, ptp_overflow_work.work);
struct timespec ts;
igb->ptp_caps.gettime(&igb->ptp_caps, &ts);
pr_debug("igb overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec);
schedule_delayed_work(&igb->ptp_overflow_work,
IGB_SYSTIM_OVERFLOW_PERIOD);
}
/**
* igb_ptp_rx_hang - detect error case when Rx timestamp registers latched
* @adapter: private network adapter structure
*
* This watchdog task is scheduled to detect error case where hardware has
* dropped an Rx packet that was timestamped when the ring is full. The
* particular error is rare but leaves the device in a state unable to timestamp
* any future packets.
*/
void igb_ptp_rx_hang(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct igb_ring *rx_ring;
u32 tsyncrxctl = E1000_READ_REG(hw, E1000_TSYNCRXCTL);
unsigned long rx_event;
int n;
if (hw->mac.type != e1000_82576)
return;
/* If we don't have a valid timestamp in the registers, just update the
* timeout counter and exit
*/
if (!(tsyncrxctl & E1000_TSYNCRXCTL_VALID)) {
adapter->last_rx_ptp_check = jiffies;
return;
}
/* Determine the most recent watchdog or rx_timestamp event */
rx_event = adapter->last_rx_ptp_check;
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
if (time_after(rx_ring->last_rx_timestamp, rx_event))
rx_event = rx_ring->last_rx_timestamp;
}
/* Only need to read the high RXSTMP register to clear the lock */
if (time_is_before_jiffies(rx_event + 5 * HZ)) {
E1000_READ_REG(hw, E1000_RXSTMPH);
adapter->last_rx_ptp_check = jiffies;
adapter->rx_hwtstamp_cleared++;
dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang");
}
}
/**
* igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp
* @adapter: Board private structure.
*
* If we were asked to do hardware stamping and such a time stamp is
* available, then it must have been for this skb here because we only
* allow only one such packet into the queue.
*/
void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct skb_shared_hwtstamps shhwtstamps;
u64 regval;
regval = E1000_READ_REG(hw, E1000_TXSTMPL);
regval |= (u64)E1000_READ_REG(hw, E1000_TXSTMPH) << 32;
igb_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps);
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
}
/**
* igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
* @q_vector: Pointer to interrupt specific structure
* @va: Pointer to address containing Rx buffer
* @skb: Buffer containing timestamp and packet
*
* This function is meant to retrieve a timestamp from the first buffer of an
* incoming frame. The value is stored in little endian format starting on
* byte 8.
*/
void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
unsigned char *va,
struct sk_buff *skb)
{
__le64 *regval = (__le64 *)va;
/*
* The timestamp is recorded in little endian format.
* DWORD: 0 1 2 3
* Field: Reserved Reserved SYSTIML SYSTIMH
*/
igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
le64_to_cpu(regval[1]));
}
/**
* igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
* @q_vector: Pointer to interrupt specific structure
* @skb: Buffer containing timestamp and packet
*
* This function is meant to retrieve a timestamp from the internal registers
* of the adapter and store it in the skb.
*/
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
struct sk_buff *skb)
{
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
u64 regval;
/*
* If this bit is set, then the RX registers contain the time stamp. No
* other packet will be time stamped until we read these registers, so
* read the registers to make them available again. Because only one
* packet can be time stamped at a time, we know that the register
* values must belong to this one here and therefore we don't need to
* compare any of the additional attributes stored for it.
*
* If nothing went wrong, then it should have a shared tx_flags that we
* can turn into a skb_shared_hwtstamps.
*/
if (!(E1000_READ_REG(hw, E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
return;
regval = E1000_READ_REG(hw, E1000_RXSTMPL);
regval |= (u64)E1000_READ_REG(hw, E1000_RXSTMPH) << 32;
igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
}
/**
* igb_ptp_hwtstamp_ioctl - control hardware time stamping
* @netdev:
* @ifreq:
* @cmd:
*
* Outgoing time stamping can be enabled and disabled. Play nice and
* disable it when requested, although it shouldn't case any overhead
* when no packet needs it. At most one packet in the queue may be
* marked for time stamping, otherwise it would be impossible to tell
* for sure to which packet the hardware time stamp belongs.
*
* Incoming time stamping has to be configured via the hardware
* filters. Not all combinations are supported, in particular event
* type has to be specified. Matching the kind of event packet is
* not supported, with the exception of "all V2 events regardless of
* level 2 or 4".
*
**/
int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct hwtstamp_config config;
u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED;
u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
u32 tsync_rx_cfg = 0;
bool is_l4 = false;
bool is_l2 = false;
u32 regval;
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
/* reserved for future extensions */
if (config.flags)
return -EINVAL;
switch (config.tx_type) {
case HWTSTAMP_TX_OFF:
tsync_tx_ctl = 0;
case HWTSTAMP_TX_ON:
break;
default:
return -ERANGE;
}
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
tsync_rx_ctl = 0;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
is_l4 = true;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
is_l4 = true;
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
is_l2 = true;
is_l4 = true;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
case HWTSTAMP_FILTER_ALL:
/*
* 82576 cannot timestamp all packets, which it needs to do to
* support both V1 Sync and Delay_Req messages
*/
if (hw->mac.type != e1000_82576) {
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
}
/* fall through */
default:
config.rx_filter = HWTSTAMP_FILTER_NONE;
return -ERANGE;
}
if (hw->mac.type == e1000_82575) {
if (tsync_rx_ctl | tsync_tx_ctl)
return -EINVAL;
return 0;
}
/*
* Per-packet timestamping only works if all packets are
* timestamped, so enable timestamping in all packets as
* long as one rx filter was configured.
*/
if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) {
tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
config.rx_filter = HWTSTAMP_FILTER_ALL;
is_l2 = true;
is_l4 = true;
if ((hw->mac.type == e1000_i210) ||
(hw->mac.type == e1000_i211)) {
regval = E1000_READ_REG(hw, E1000_RXPBS);
regval |= E1000_RXPBS_CFG_TS_EN;
E1000_WRITE_REG(hw, E1000_RXPBS, regval);
}
}
/* enable/disable TX */
regval = E1000_READ_REG(hw, E1000_TSYNCTXCTL);
regval &= ~E1000_TSYNCTXCTL_ENABLED;
regval |= tsync_tx_ctl;
E1000_WRITE_REG(hw, E1000_TSYNCTXCTL, regval);
/* enable/disable RX */
regval = E1000_READ_REG(hw, E1000_TSYNCRXCTL);
regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK);
regval |= tsync_rx_ctl;
E1000_WRITE_REG(hw, E1000_TSYNCRXCTL, regval);
/* define which PTP packets are time stamped */
E1000_WRITE_REG(hw, E1000_TSYNCRXCFG, tsync_rx_cfg);
/* define ethertype filter for timestamped packets */
if (is_l2)
E1000_WRITE_REG(hw, E1000_ETQF(3),
(E1000_ETQF_FILTER_ENABLE | /* enable filter */
E1000_ETQF_1588 | /* enable timestamping */
ETH_P_1588)); /* 1588 eth protocol type */
else
E1000_WRITE_REG(hw, E1000_ETQF(3), 0);
/* L4 Queue Filter[3]: filter by destination port and protocol */
if (is_l4) {
u32 ftqf = (IPPROTO_UDP /* UDP */
| E1000_FTQF_VF_BP /* VF not compared */
| E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */
| E1000_FTQF_MASK); /* mask all inputs */
ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */
E1000_WRITE_REG(hw, E1000_IMIR(3), htons(PTP_EV_PORT));
E1000_WRITE_REG(hw, E1000_IMIREXT(3),
(E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP));
if (hw->mac.type == e1000_82576) {
/* enable source port check */
E1000_WRITE_REG(hw, E1000_SPQF(3), htons(PTP_EV_PORT));
ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
}
E1000_WRITE_REG(hw, E1000_FTQF(3), ftqf);
} else {
E1000_WRITE_REG(hw, E1000_FTQF(3), E1000_FTQF_MASK);
}
E1000_WRITE_FLUSH(hw);
/* clear TX/RX time stamp registers, just to be sure */
regval = E1000_READ_REG(hw, E1000_TXSTMPL);
regval = E1000_READ_REG(hw, E1000_TXSTMPH);
regval = E1000_READ_REG(hw, E1000_RXSTMPL);
regval = E1000_READ_REG(hw, E1000_RXSTMPH);
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-EFAULT : 0;
}
void igb_ptp_init(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
switch (hw->mac.type) {
case e1000_82576:
snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
adapter->ptp_caps.owner = THIS_MODULE;
adapter->ptp_caps.max_adj = 999999881;
adapter->ptp_caps.n_ext_ts = 0;
adapter->ptp_caps.pps = 0;
adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576;
adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;
adapter->ptp_caps.gettime = igb_ptp_gettime_82576;
adapter->ptp_caps.settime = igb_ptp_settime_82576;
adapter->ptp_caps.enable = igb_ptp_enable;
adapter->cc.read = igb_ptp_read_82576;
adapter->cc.mask = CLOCKSOURCE_MASK(64);
adapter->cc.mult = 1;
adapter->cc.shift = IGB_82576_TSYNC_SHIFT;
/* Dial the nominal frequency. */
E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 |
INCVALUE_82576);
break;
case e1000_82580:
case e1000_i350:
case e1000_i354:
snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
adapter->ptp_caps.owner = THIS_MODULE;
adapter->ptp_caps.max_adj = 62499999;
adapter->ptp_caps.n_ext_ts = 0;
adapter->ptp_caps.pps = 0;
adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580;
adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;
adapter->ptp_caps.gettime = igb_ptp_gettime_82576;
adapter->ptp_caps.settime = igb_ptp_settime_82576;
adapter->ptp_caps.enable = igb_ptp_enable;
adapter->cc.read = igb_ptp_read_82580;
adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580);
adapter->cc.mult = 1;
adapter->cc.shift = 0;
/* Enable the timer functions by clearing bit 31. */
E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0);
break;
case e1000_i210:
case e1000_i211:
snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
adapter->ptp_caps.owner = THIS_MODULE;
adapter->ptp_caps.max_adj = 62499999;
adapter->ptp_caps.n_ext_ts = 0;
adapter->ptp_caps.pps = 0;
adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580;
adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210;
adapter->ptp_caps.gettime = igb_ptp_gettime_i210;
adapter->ptp_caps.settime = igb_ptp_settime_i210;
adapter->ptp_caps.enable = igb_ptp_enable;
/* Enable the timer functions by clearing bit 31. */
E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0);
break;
default:
adapter->ptp_clock = NULL;
return;
}
E1000_WRITE_FLUSH(hw);
spin_lock_init(&adapter->tmreg_lock);
INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
/* Initialize the clock and overflow work for devices that need it. */
if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) {
struct timespec ts = ktime_to_timespec(ktime_get_real());
igb_ptp_settime_i210(&adapter->ptp_caps, &ts);
} else {
timecounter_init(&adapter->tc, &adapter->cc,
ktime_to_ns(ktime_get_real()));
INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
igb_ptp_overflow_check);
schedule_delayed_work(&adapter->ptp_overflow_work,
IGB_SYSTIM_OVERFLOW_PERIOD);
}
/* Initialize the time sync interrupts for devices that support it. */
if (hw->mac.type >= e1000_82580) {
E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS);
E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS);
}
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
&adapter->pdev->dev);
if (IS_ERR(adapter->ptp_clock)) {
adapter->ptp_clock = NULL;
dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n");
} else {
dev_info(&adapter->pdev->dev, "added PHC on %s\n",
adapter->netdev->name);
adapter->flags |= IGB_FLAG_PTP;
}
}
/**
* igb_ptp_stop - Disable PTP device and stop the overflow check.
* @adapter: Board private structure.
*
* This function stops the PTP support and cancels the delayed work.
**/
void igb_ptp_stop(struct igb_adapter *adapter)
{
switch (adapter->hw.mac.type) {
case e1000_82576:
case e1000_82580:
case e1000_i350:
case e1000_i354:
cancel_delayed_work_sync(&adapter->ptp_overflow_work);
break;
case e1000_i210:
case e1000_i211:
/* No delayed work to cancel. */
break;
default:
return;
}
cancel_work_sync(&adapter->ptp_tx_work);
if (adapter->ptp_tx_skb) {
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
}
if (adapter->ptp_clock) {
ptp_clock_unregister(adapter->ptp_clock);
dev_info(&adapter->pdev->dev, "removed PHC on %s\n",
adapter->netdev->name);
adapter->flags &= ~IGB_FLAG_PTP;
}
}
/**
* igb_ptp_reset - Re-enable the adapter for PTP following a reset.
* @adapter: Board private structure.
*
* This function handles the reset work required to re-enable the PTP device.
**/
void igb_ptp_reset(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
if (!(adapter->flags & IGB_FLAG_PTP))
return;
switch (adapter->hw.mac.type) {
case e1000_82576:
/* Dial the nominal frequency. */
E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 |
INCVALUE_82576);
break;
case e1000_82580:
case e1000_i350:
case e1000_i354:
case e1000_i210:
case e1000_i211:
/* Enable the timer functions and interrupts. */
E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0);
E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS);
E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS);
break;
default:
/* No work to do. */
return;
}
/* Re-initialize the timer. */
if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) {
struct timespec ts = ktime_to_timespec(ktime_get_real());
igb_ptp_settime_i210(&adapter->ptp_caps, &ts);
} else {
timecounter_init(&adapter->tc, &adapter->cc,
ktime_to_ns(ktime_get_real()));
}
}

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -52,18 +52,48 @@ struct igb_reg_test {
#define TABLE64_TEST_LO 5
#define TABLE64_TEST_HI 6
/* i210 reg test */
static struct igb_reg_test reg_test_i210[] = {
{ 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_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 },
/* RDH is read-only for i210, only test RDT. */
{ E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
{ 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_TDT(0), 0x100, 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,
0x900FFFFF, 0xFFFFFFFF },
{ E1000_MTA, 0, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0 }
};
/* 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 },
{ E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 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, 0x000FFFF0, 0x000FFFFF },
{ 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, 0x000FFFF0, 0x000FFFFF },
{ 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 },
@ -72,10 +102,10 @@ static struct igb_reg_test reg_test_i350[] = {
{ 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_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, 0x000FFFF0, 0x000FFFFF },
{ 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 },

View file

@ -0,0 +1,815 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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 */
#ifdef __VMKNETDDI_QUEUEOPS__
int igb_set_rxqueue_macfilter(struct net_device *netdev, int queue,
u8 *mac_addr)
{
int err = 0;
struct igb_adapter *adapter = netdev_priv(netdev);
struct igb_ring *rx_ring = adapter->rx_ring[queue];
if ((queue < 0) || (queue >= adapter->num_rx_queues)) {
DPRINTK(DRV, ERR, "Invalid RX Queue %u specified\n", queue);
return -EADDRNOTAVAIL;
}
/* Note: Broadcast address is used to disable the MAC filter*/
if (!is_valid_ether_addr(mac_addr)) {
/* Clear ring addr */
DPRINTK(DRV, DEBUG,
"disabling MAC filter on RX Queue[%d]\n", queue);
igb_del_mac_filter(adapter, rx_ring->mac_addr, queue);
memset(rx_ring->mac_addr, 0xFF, NODE_ADDRESS_SIZE);
return -EADDRNOTAVAIL;
}
DPRINTK(DRV, DEBUG,
"enabling MAC filter [[0x%X:0x%X:0x%X:0x%X:0x%X:0x%X]] "
"on RX Queue[%d]\n", mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5], queue);
/* Store in ring */
memcpy(rx_ring->mac_addr, mac_addr, NODE_ADDRESS_SIZE);
igb_add_mac_filter(adapter, rx_ring->mac_addr, queue);
return err;
}
static int igb_get_netqueue_features(vmknetddi_queueop_get_features_args_t *args)
{
args->features = VMKNETDDI_QUEUEOPS_FEATURE_RXQUEUES |
VMKNETDDI_QUEUEOPS_FEATURE_TXQUEUES;
return VMKNETDDI_QUEUEOPS_OK;
}
static int igb_get_queue_count(vmknetddi_queueop_get_queue_count_args_t *args)
{
struct net_device *netdev = args->netdev;
struct igb_adapter *adapter = netdev_priv(netdev);
if (args->type == VMKNETDDI_QUEUEOPS_QUEUE_TYPE_TX) {
args->count = adapter->num_tx_queues - 1;
} else if (args->type == VMKNETDDI_QUEUEOPS_QUEUE_TYPE_RX) {
args->count = adapter->num_rx_queues - 1;
} else {
DPRINTK(DRV, ERR, "invalid queue type\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
return VMKNETDDI_QUEUEOPS_OK;
}
static int igb_get_filter_count(vmknetddi_queueop_get_filter_count_args_t *args)
{
args->count = 1;
return VMKNETDDI_QUEUEOPS_OK;
}
static int igb_alloc_rx_queue(struct net_device *netdev,
vmknetddi_queueops_queueid_t *p_qid,
struct napi_struct **napi_p)
{
struct igb_adapter *adapter = netdev_priv(netdev);
if (adapter->n_rx_queues_allocated >= adapter->num_rx_queues) {
DPRINTK(DRV, ERR, "igb_alloc_rx_queue: no free rx queues\n");
return VMKNETDDI_QUEUEOPS_ERR;
} else {
int i;
for (i = 1; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = adapter->rx_ring[i];
if (!ring->allocated) {
ring->allocated = TRUE;
*p_qid = VMKNETDDI_QUEUEOPS_MK_RX_QUEUEID(i);
DPRINTK(DRV, DEBUG,
"allocated VMDQ rx queue=%d\n", i);
*napi_p = &ring->q_vector->napi;
adapter->n_rx_queues_allocated++;
return VMKNETDDI_QUEUEOPS_OK;
}
}
DPRINTK(DRV, ERR, "no free rx queues found!\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
}
static int igb_alloc_tx_queue(struct net_device *netdev,
vmknetddi_queueops_queueid_t *p_qid,
u16 *queue_mapping)
{
struct igb_adapter *adapter = netdev_priv(netdev);
if (adapter->n_tx_queues_allocated >= adapter->num_tx_queues) {
DPRINTK(DRV, ERR, "igb_alloc_tx_queue: no free tx queues\n");
return VMKNETDDI_QUEUEOPS_ERR;
} else {
int i;
for (i = 1; i < adapter->num_tx_queues; i++) {
struct igb_ring *ring = adapter->tx_ring[i];
if (!ring->allocated) {
ring->allocated = TRUE;
*p_qid = VMKNETDDI_QUEUEOPS_MK_TX_QUEUEID(i);
*queue_mapping = i;
DPRINTK(DRV, DEBUG,
"allocated VMDQ tx queue=%d\n", i);
adapter->n_tx_queues_allocated++;
return VMKNETDDI_QUEUEOPS_OK;
}
}
DPRINTK(DRV, ERR, "no free tx queues found!\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
}
static int igb_alloc_queue(vmknetddi_queueop_alloc_queue_args_t *args)
{
struct net_device *netdev = args->netdev;
struct igb_adapter *adapter = netdev_priv(netdev);
if (args->type == VMKNETDDI_QUEUEOPS_QUEUE_TYPE_TX) {
return igb_alloc_tx_queue(args->netdev, &args->queueid,
&args->queue_mapping);
} else if (args->type == VMKNETDDI_QUEUEOPS_QUEUE_TYPE_RX) {
return igb_alloc_rx_queue(args->netdev, &args->queueid,
&args->napi);
} else {
DPRINTK(DRV, ERR, "invalid queue type\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
}
static int
igb_free_rx_queue(struct net_device *netdev,
vmknetddi_queueops_queueid_t qid)
{
struct igb_adapter *adapter = netdev_priv(netdev);
u16 queue = VMKNETDDI_QUEUEOPS_QUEUEID_VAL(qid);
struct igb_ring *ring = adapter->rx_ring[queue];
if (!ring->allocated) {
DPRINTK(DRV, ERR, "rx queue %d not allocated\n", queue);
return VMKNETDDI_QUEUEOPS_ERR;
}
DPRINTK(DRV, DEBUG, "freed VMDQ rx queue=%d\n", queue);
ring->allocated = FALSE;
adapter->n_rx_queues_allocated--;
return VMKNETDDI_QUEUEOPS_OK;
}
static int
igb_free_tx_queue(struct net_device *netdev,
vmknetddi_queueops_queueid_t qid)
{
struct igb_adapter *adapter = netdev_priv(netdev);
u16 queue = VMKNETDDI_QUEUEOPS_QUEUEID_VAL(qid);
if (!adapter->tx_ring[queue]->allocated) {
DPRINTK(DRV, ERR, "tx queue %d not allocated\n", queue);
return VMKNETDDI_QUEUEOPS_ERR;
}
DPRINTK(DRV, DEBUG, "freed VMDQ tx queue=%d\n", queue);
adapter->tx_ring[queue]->allocated = FALSE;
adapter->n_tx_queues_allocated--;
return VMKNETDDI_QUEUEOPS_OK;
}
static int
igb_free_queue(vmknetddi_queueop_free_queue_args_t *args)
{
struct net_device *netdev = args->netdev;
struct igb_adapter *adapter = netdev_priv(netdev);
if (VMKNETDDI_QUEUEOPS_IS_TX_QUEUEID(args->queueid)) {
return igb_free_tx_queue(netdev, args->queueid);
} else if (VMKNETDDI_QUEUEOPS_IS_RX_QUEUEID(args->queueid)) {
return igb_free_rx_queue(netdev, args->queueid);
} else {
DPRINTK(DRV, ERR, "invalid queue type\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
}
static int
igb_get_queue_vector(vmknetddi_queueop_get_queue_vector_args_t *args)
{
int qid;
struct net_device *netdev = args->netdev;
struct igb_adapter *adapter = netdev_priv(netdev);
/* Assuming RX queue id's are received */
qid = VMKNETDDI_QUEUEOPS_QUEUEID_VAL(args->queueid);
args->vector = adapter->msix_entries[qid].vector;
return VMKNETDDI_QUEUEOPS_OK;
}
static int
igb_get_default_queue(vmknetddi_queueop_get_default_queue_args_t *args)
{
struct net_device *netdev = args->netdev;
struct igb_adapter *adapter = netdev_priv(netdev);
if (args->type == VMKNETDDI_QUEUEOPS_QUEUE_TYPE_RX) {
args->napi = &adapter->rx_ring[0]->q_vector->napi;
args->queueid = VMKNETDDI_QUEUEOPS_MK_RX_QUEUEID(0);
return VMKNETDDI_QUEUEOPS_OK;
} else if (args->type == VMKNETDDI_QUEUEOPS_QUEUE_TYPE_TX) {
args->queueid = VMKNETDDI_QUEUEOPS_MK_TX_QUEUEID(0);
return VMKNETDDI_QUEUEOPS_OK;
} else {
return VMKNETDDI_QUEUEOPS_ERR;
}
}
static int
igb_apply_rx_filter(vmknetddi_queueop_apply_rx_filter_args_t *args)
{
int rval;
u8 *macaddr;
u16 queue = VMKNETDDI_QUEUEOPS_QUEUEID_VAL(args->queueid);
struct igb_adapter *adapter = netdev_priv(args->netdev);
if (!VMKNETDDI_QUEUEOPS_IS_RX_QUEUEID(args->queueid)) {
DPRINTK(DRV, ERR, "not an rx queue 0x%x\n",
args->queueid);
return VMKNETDDI_QUEUEOPS_ERR;
}
if (vmknetddi_queueops_get_filter_class(&args->filter)
!= VMKNETDDI_QUEUEOPS_FILTER_MACADDR) {
DPRINTK(DRV, ERR, "only mac filters supported\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
if (!adapter->rx_ring[queue]->allocated) {
DPRINTK(DRV, ERR, "queue not allocated\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
if (adapter->rx_ring[queue]->active) {
DPRINTK(DRV, ERR, "filter count exceeded\n");
return VMKNETDDI_QUEUEOPS_ERR;
}
macaddr = vmknetddi_queueops_get_filter_macaddr(&args->filter);
rval = igb_set_rxqueue_macfilter(args->netdev, queue, macaddr);
if (rval == 0) {
adapter->rx_ring[queue]->active = TRUE;
/* force to 0 since we only support one filter per queue */
args->filterid = VMKNETDDI_QUEUEOPS_MK_FILTERID(0);
return VMKNETDDI_QUEUEOPS_OK;
} else {
return VMKNETDDI_QUEUEOPS_ERR;
}
}
static int
igb_remove_rx_filter(vmknetddi_queueop_remove_rx_filter_args_t *args)
{
int rval;
u16 cidx = VMKNETDDI_QUEUEOPS_QUEUEID_VAL(args->queueid);
u16 fidx = VMKNETDDI_QUEUEOPS_FILTERID_VAL(args->filterid);
struct igb_adapter *adapter = netdev_priv(args->netdev);
u8 macaddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
DPRINTK(DRV, DEBUG, "removing filter on cidx=%d, fidx=%d\n",
cidx, fidx);
/* This will return an error because broadcast is not a valid
* Ethernet address, so ignore and carry on
*/
rval = igb_set_rxqueue_macfilter(args->netdev, cidx, macaddr);
adapter->rx_ring[cidx]->active = FALSE;
return rval;
}
static int
igb_get_queue_stats(vmknetddi_queueop_get_stats_args_t *args)
{
return VMKNETDDI_QUEUEOPS_ERR;
}
static int
igb_get_netqueue_version(vmknetddi_queueop_get_version_args_t *args)
{
return vmknetddi_queueops_version(args);
}
static int igb_set_tx_priority(vmknetddi_queueop_set_tx_priority_args_t *args)
{
/* Not supported */
return VMKNETDDI_QUEUEOPS_OK;
}
int
igb_netqueue_ops(vmknetddi_queueops_op_t op, void *args)
{
switch (op) {
case VMKNETDDI_QUEUEOPS_OP_GET_VERSION:
return igb_get_netqueue_version(
(vmknetddi_queueop_get_version_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_GET_FEATURES:
return igb_get_netqueue_features(
(vmknetddi_queueop_get_features_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_GET_QUEUE_COUNT:
return igb_get_queue_count(
(vmknetddi_queueop_get_queue_count_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_GET_FILTER_COUNT:
return igb_get_filter_count(
(vmknetddi_queueop_get_filter_count_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_ALLOC_QUEUE:
return igb_alloc_queue(
(vmknetddi_queueop_alloc_queue_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_FREE_QUEUE:
return igb_free_queue(
(vmknetddi_queueop_free_queue_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_GET_QUEUE_VECTOR:
return igb_get_queue_vector(
(vmknetddi_queueop_get_queue_vector_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_GET_DEFAULT_QUEUE:
return igb_get_default_queue(
(vmknetddi_queueop_get_default_queue_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_APPLY_RX_FILTER:
return igb_apply_rx_filter(
(vmknetddi_queueop_apply_rx_filter_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_REMOVE_RX_FILTER:
return igb_remove_rx_filter(
(vmknetddi_queueop_remove_rx_filter_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_GET_STATS:
return igb_get_queue_stats(
(vmknetddi_queueop_get_stats_args_t *)args);
break;
case VMKNETDDI_QUEUEOPS_OP_SET_TX_PRIORITY:
return igb_set_tx_priority(
(vmknetddi_queueop_set_tx_priority_args_t *)args);
break;
default:
return VMKNETDDI_QUEUEOPS_ERR;
}
return VMKNETDDI_QUEUEOPS_ERR;
}
#endif /* __VMKNETDDI_QUEUEOPS__ */

View file

@ -0,0 +1,51 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2013 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 */
#ifdef __VMKLNX__
#ifdef __VMKNETDDI_QUEUEOPS__
extern int igb_netqueue_ops(vmknetddi_queueops_op_t op, void *args);
#endif
#endif
#endif /* _IGB_VMDQ_H_ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -33,6 +33,11 @@
#include "vmkapi.h"
#define ESX40_PRODUCT_VER "4.0.0"
#define ESX41_PRODUCT_VER "4.1.0"
#define ESX50_PRODUCT_VER "5.0.0"
#define ESX51_PRODUCT_VER "5.1.0"
/* disable features that VMware ESX does not support */
#ifndef CONFIG_PM
@ -48,9 +53,8 @@
#define vmalloc_node(a,b) vmalloc(a)
#define skb_record_rx_queue(a, b) \
if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) \
vmknetddi_queueops_set_skb_queueid((a), \
VMKNETDDI_QUEUEOPS_MK_RX_QUEUEID((b)));
vmknetddi_queueops_set_skb_queueid((a), \
VMKNETDDI_QUEUEOPS_MK_RX_QUEUEID((b)));
#define skb_trim _kc_skb_trim
@ -65,8 +69,6 @@ static inline void _kc_skb_trim(struct sk_buff *skb, unsigned int len)
skb->tail = skb->data + len;
}
}
/* disable pskb_trim usage for now - should break lots of stuff */
#define pskb_trim(a,b)
/* Alternate __VMKLNX__ DMA memory allocation stuff */
#define alloc_page(A) __get_free_pages(A, 0)
@ -81,6 +83,7 @@ static inline void _kc_skb_trim(struct sk_buff *skb, unsigned int len)
/*
* A couple of quick hacks for working with esx40
*/
#define vmknetddi_queueops_queue_features_t unsigned int
#define HAVE_NETDEV_NAPI_LIST
#define vmk_set_module_version(x,y) 1
#define VMKNETDDI_REGISTER_QUEUEOPS(ndev, ops) \
@ -100,3 +103,10 @@ static inline void _kc_skb_trim(struct sk_buff *skb, unsigned int len)
#define device_set_wakeup_enable(d, w) device_init_wakeup(d, w);
#define nr_cpu_ids smp_num_cpus
#define ESX_ALLOC_PERCPU( type ) \
kmalloc(sizeof(type) * nr_cpu_ids, GFP_KERNEL)
#define ESX_FREE_PERCPU( ptr ) kfree(ptr)
#define ESX_PER_CPU_PTR( ptr, cpu, type ) (((cpu) < nr_cpu_ids)? \
((typeof(ptr))((char*)(ptr) + (cpu) * sizeof(type))):NULL)
#define __percpu

View file

@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2009 Intel Corporation.
Copyright(c) 2007-2013 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,
@ -894,8 +894,6 @@ struct mii_ioctl_data;
#define mii_ethtool_sset _kc_mii_ethtool_sset
#undef mii_check_link
#define mii_check_link _kc_mii_check_link
#undef generic_mii_ioctl
#define generic_mii_ioctl _kc_generic_mii_ioctl
extern int _kc_mii_link_ok (struct mii_if_info *mii);
extern int _kc_mii_nway_restart (struct mii_if_info *mii);
extern int _kc_mii_ethtool_gset(struct mii_if_info *mii,
@ -903,9 +901,13 @@ extern int _kc_mii_ethtool_gset(struct mii_if_info *mii,
extern int _kc_mii_ethtool_sset(struct mii_if_info *mii,
struct ethtool_cmd *ecmd);
extern void _kc_mii_check_link (struct mii_if_info *mii);
#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) )
#undef generic_mii_ioctl
#define generic_mii_ioctl _kc_generic_mii_ioctl
extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
struct mii_ioctl_data *mii_data, int cmd,
unsigned int *duplex_changed);
#endif /* > 2.4.6 */
struct _kc_pci_dev_ext {
@ -1091,6 +1093,7 @@ void _kc_mii_check_link (struct mii_if_info *mii)
netif_carrier_off(mii->dev);
}
#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) )
int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
struct mii_ioctl_data *mii_data, int cmd,
unsigned int *duplex_chg_out)
@ -1165,4 +1168,5 @@ int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
return rc;
}
#endif /* > 2.4.6 */

View file

@ -4413,6 +4413,8 @@ int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue)
/* Dont allow programming of duplicate MAC
* address on the same PF for different VFs(queues)
*/
if (!compare_ether_addr(addr, hw->mac.perm_addr))
return i;
if (!compare_ether_addr
(addr, adapter->mac_table[i].addr)) {
if (adapter->mac_table[i].queue == queue) {
@ -4473,6 +4475,8 @@ int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, u8* addr, u16 queue)
return -EINVAL;
for (i = 0; i < hw->mac.num_rar_entries; i++) {
if (!compare_ether_addr(addr, hw->mac.perm_addr))
return 0;
if (!compare_ether_addr(addr, adapter->mac_table[i].addr) &&
adapter->mac_table[i].queue == queue) {
adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED;

View file

@ -25,7 +25,7 @@
/*
* Source file for NIC routines to access the Phantom hardware
*
* $Id: //depot/vmkdrivers/prod2013-stage-rel/src_9/drivers/net/nx_nic/unm_nic_hw.c#1 $
* $Id: //depot/vmkdrivers/vsphere55u1/src_9/drivers/net/nx_nic/unm_nic_hw.c#1 $
*
*/
#include <linux/delay.h>

View file

@ -17703,6 +17703,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
features |= NETIF_F_TSO_ECN;
}
#if defined(__VMKLNX__) && defined(TG3_INBOX)
/*
* Disable TSO to avoid the data corruption issue happened when
* a 9KB+ buffer straddling a 4GB boundary. Please refer to
* PR 1148150.
*/
features &= ~(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN);
tg3_flag_clear(tp, TSO_CAPABLE);
tg3_flag_clear(tp, TSO_BUG);
#endif
#if defined(__VMKLNX__)
/* VMWare does not have skb_gso_segment() to workaround TSO_BUG */
if (tg3_flag(tp, TSO_BUG))

View file

@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "8.2.3.1-128vmw"
#define LPFC_DRIVER_VERSION "8.2.3.1-129vmw"
#if defined(__VMKLNX__)
/*

View file

@ -2510,7 +2510,6 @@ static void megasas_hotplug_work(void *arg)
* Because scsi_device_lookup() takes a reference on the device,
* should decrement reference count before removing it.
*/
vmklnx_scsi_device_hot_removed(device);
scsi_device_put(device);
scsi_remove_device(device);
}
@ -2525,7 +2524,6 @@ static void megasas_hotplug_work(void *arg)
* Because scsi_device_lookup() takes a reference on the device,
* should decrement reference count before removing it.
*/
vmklnx_scsi_device_hot_removed(device);
scsi_device_put(device);
scsi_remove_device(device);
} else {

View file

@ -3026,6 +3026,7 @@ mpt2sas_base_get_sata_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz)
{
Mpi2SataPassthroughRequest_t *mpi_request;
Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
u16 smid;
u32 ioc_state;
unsigned long timeleft;
@ -3109,7 +3110,7 @@ mpt2sas_base_get_sata_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
sizeof(Mpi2SataPassthroughRequest_t)/4);
if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
issue_reset = 1;
goto issue_host_reset;
goto issue_target_reset;
}
if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) {
memcpy(mpi_reply, ioc->config_cmds.reply,
@ -3122,12 +3123,40 @@ mpt2sas_base_get_sata_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
goto out;
issue_host_reset:
if (issue_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
issue_target_reset:
if (issue_reset) {
smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
if (!smid) {
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a tm smid\n",
ioc->name, __func__);
rc = -EAGAIN;
goto out;
}
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
"(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
ioc->tm_tr_cb_idx));
ioc->config_cmds.status = MPT2_CMD_PENDING;
request = mpt2sas_base_get_msg_frame(ioc, smid);
mpi_request_tm = (Mpi2SCSITaskManagementRequest_t *)request;
memset(mpi_request_tm, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
mpi_request_tm->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request_tm->DevHandle = cpu_to_le16(handle);
mpi_request_tm->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
ioc->config_cmds.smid = smid;
mpt2sas_base_put_smid_hi_priority(ioc, smid);
init_completion(&ioc->config_cmds.done);
timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
msecs_to_jiffies(30000));
ioc->config_cmds.status = MPT2_CMD_NOT_USED;
rc = -EFAULT;
memset(mpi_reply, 0, sizeof(Mpi2SataPassthroughReply_t));
}
rc = -EAGAIN;
out:
mutex_unlock(&ioc->config_cmds.mutex);
pci_free_consistent(ioc->pdev, sz, buffer, dma_addr);

View file

@ -8224,7 +8224,6 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
break;
}
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
vmklnx_scsi_target_hot_removed(sas_device->starget);
#endif
_scsih_device_remove_by_handle(ioc, handle);
break;

View file

@ -7,7 +7,7 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "902.k1.1-11vmw"
#define QLA2XXX_VERSION "902.k1.1-12vmw"
#define QLA_DRIVER_MAJOR_VER 9
#define QLA_DRIVER_MINOR_VER 0

View file

@ -5998,6 +5998,9 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
/* call completion callback */
qc->complete_fn(qc);
#if defined(__VMKLNX__)
ata_restart_waitq(ap);
#endif /* defined(__VMKLNX__) */
}
static void fill_result_tf(struct ata_queued_cmd *qc)
@ -6100,6 +6103,15 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
ata_verify_xfer(qc);
__ata_qc_complete(qc);
#if defined(__VMKLNX__)
/* Fixing PR 1173296 */
if (unlikely((ehi->dev_action[dev->devno] & ATA_EH_REVALIDATE) &&
(ap->pflags & ATA_PFLAG_EH_PENDING))) {
ata_port_printk(ap, KERN_INFO,
"ata_qc_complete, dev needs revalidation, calling EH\n");
wake_up_process(ap->scsi_host->ehandler);
}
#endif /* defined(__VMKLNX__) */
} else {
if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
return;
@ -6951,7 +6963,16 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
DPRINTK("ENTER\n");
#if defined(__VMKLNX__)
struct vmk_ata_all_port_wq *ata_wq;
ap = kzalloc((sizeof(*ap) +
sizeof(struct vmk_ata_all_port_wq)), GFP_KERNEL);
ATA_GET_WAITQ_STRUCT(ap, ata_wq);
ATA_WQ_INIT(ata_wq);
#else
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
#endif /* defined(__VMKLNX__) */
if (!ap)
return NULL;

View file

@ -1110,9 +1110,9 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
spin_unlock_irqrestore(ap->lock, flags);
}
/**
/*
* ata_eh_done - EH action complete
* @ap: target ATA port
* @ap: target ATA port
* @dev: target ATA dev for per-dev action (can be NULL)
* @action: action just completed
*
@ -1263,7 +1263,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
return 0;
}
/**
/*
* atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
* @dev: device to perform REQUEST_SENSE to
* @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)

View file

@ -52,7 +52,7 @@ static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val)
* sata_pmp_write - write PMP register
* @link: link to write PMP register for
* @reg: register to write
* @r_val: value to write
* @val: value to write
*
* Write PMP register.
*
@ -287,7 +287,7 @@ int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
/**
* ata_std_postreset - standard postreset method for PMP link
* @link: the target ata_link
* @classes: classes of attached devices
* @class: classes of attached devices
*
* This function is invoked after a successful reset. Note that
* the device might have been reset more than once using

View file

@ -1839,8 +1839,13 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
{
struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
int rc;
int rc = 0;
#if defined(__VMKLNX__)
struct vmk_ata_all_port_wq *ata_wq = NULL;
ATA_GET_WAITQ_STRUCT(ap, ata_wq);
#endif /* defined(__VMKLNX__) */
VPRINTK("ENTER\n");
qc = ata_scsi_qc_new(dev, cmd, done);
@ -1877,14 +1882,33 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
if (xlat_func(qc))
goto early_finish;
#if defined(__VMKLNX__)
if (!ATA_WQ_EMPTY(ata_wq)) {
if (!ata_save_waitq(ap, qc)) {
goto noerror_exit;
} else {
goto defer;
}
}
if (ap->ops->qc_defer) {
if ((rc = ap->ops->qc_defer(qc))) {
if (!ata_save_waitq(ap, qc)) {
goto noerror_exit;
} else {
goto defer;
}
}
}
#else
if (ap->ops->qc_defer) {
if ((rc = ap->ops->qc_defer(qc)))
goto defer;
}
#endif /* defined(__VMKLNX__) */
/* select device, send command to hardware */
ata_qc_issue(qc);
noerror_exit:
VPRINTK("EXIT\n");
return 0;
@ -4090,6 +4114,69 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
spin_lock(shost->host_lock);
return rc;
}
#if defined(__VMKLNX__)
/*
* ata_save_waitq
* @ap: ATA port to which the command was being sent
* @qc: command to issue to device
*
* Save qc command into waiting queue list
* because ata_scsi_qc_new can't allocate more than 31
* commands, the waiting queue's depth is not over 31,
* we will hold qc command which is allocate and defered
* by NCQ/Non-NCQ defer.
*
* LOCKING
* spin_lock(ap lock)
*
*/
int ata_save_waitq(struct ata_port *ap, struct ata_queued_cmd *qc)
{
struct vmk_ata_all_port_wq *ata_wq = NULL;
ATA_GET_WAITQ_STRUCT(ap, ata_wq);
if (ATA_WQ_FULL(ata_wq))
return -1;
ATA_WQ_ADD(ata_wq, qc);
return 0;
}
/*
* ata_restart_waitq
* @ap: ATA port to which the command was being sent
*
* start waiting queue work and try to issue command
*
* LOCKING
* spin_lock(ap lock)
*
*/
void ata_restart_waitq(struct ata_port *ap)
{
struct vmk_ata_all_port_wq *ata_wq = NULL;
struct ata_queued_cmd *qc = NULL;
int rc = 0;
ATA_GET_WAITQ_STRUCT(ap, ata_wq);
ATA_WQ_HEAD(ata_wq, qc);
while (qc != NULL) {
if (ap->ops->qc_defer) {
if ((rc = ap->ops->qc_defer(qc))) {
return;
}
}
ATA_WQ_REMOVE(ata_wq, qc);
ata_qc_issue(qc);
ATA_WQ_HEAD(ata_wq, qc);
}
return;
}
#endif /* defined(__VMKLNX__) */
/**
* ata_scsi_simulate - simulate SCSI command on ATA device

View file

@ -38,6 +38,59 @@ struct ata_scsi_args {
void (*done)(struct scsi_cmnd *);
};
#if defined(__VMKLNX__)
#define ATA_WAITQ_ARRAY_SIZE ATA_MAX_QUEUE
struct vmk_ata_all_port_wq {
struct ata_queued_cmd *qc[ATA_WAITQ_ARRAY_SIZE];
int head;
int tail;
int count;
};
#define ATA_GET_WAITQ_STRUCT(ap, ata_wq) \
do { \
ata_wq = (struct vmk_ata_all_port_wq *)((void *)(ap) \
+ sizeof(*ap)); \
} while (0)
#define ATA_WQ_INIT(wq) \
do { \
(wq)->head = (wq)->tail = (wq)->count = 0; \
} while (0)
#define ATA_WQ_FULL(wq) ((wq)->count == ATA_WAITQ_ARRAY_SIZE)
#define ATA_WQ_EMPTY(wq) ((wq)->count == 0)
#define ATA_WQ_ADD(wq, qc) \
do { \
(wq)->qc[(wq)->tail++] = qc; \
if ((wq)->tail >= ATA_WAITQ_ARRAY_SIZE) { \
(wq)->tail = 0; \
} \
(wq)->count++; \
} while (0)
#define ATA_WQ_REMOVE(wq, qc) \
do { \
qc = (wq)->qc[(wq)->head++]; \
if ((wq)->head >= ATA_WAITQ_ARRAY_SIZE) { \
(wq)->head = 0; \
} \
(wq)->count--; \
} while (0)
#define ATA_WQ_HEAD(wq, qc) \
do { \
qc = (wq)->qc[(wq)->head]; \
if ((wq)->count == 0) { \
qc = NULL; \
} \
} while (0)
#endif /* defined(__VMKLNX__) */
/* libata-core.c */
enum {
/* flags for ata_dev_read_id() */
@ -53,6 +106,14 @@ enum {
ATA_DNXFER_QUIET = (1 << 31),
};
#if defined(__VMKLNX__)
int ata_save_waitq(struct ata_port *ap, struct ata_queued_cmd *qc);
extern void ata_restart_waitq(struct ata_port *ap);
extern void ata_waitq_delete_all(struct ata_port *ap);
#endif /* defined(__VMKLNX__) */
extern unsigned int ata_print_id;
extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled;

View file

@ -495,6 +495,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
/**
* fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it
* @fip: The FCoE controller for the ELS frame
* @lport: local port
* @dtype: The FIP descriptor type for the frame
* @skb: The FCoE ELS frame including FC header but no FCoE headers
*
@ -1532,6 +1533,7 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
/**
* fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response
* @fip: The FCoE controller
* @lport: not in use
* @fp: The FC frame to snoop
*
* Snoop potential response to FLOGI or even incoming FLOGI.
@ -1648,7 +1650,7 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
/**
* fcoe_libfc_config() - Sets up libfc related properties for local port
* @lp: The local port to configure libfc for
* @lport: The local port to configure libfc for
* @tt: The libfc function template
*
* Returns : 0 for success

View file

@ -76,6 +76,7 @@ void fc_disc_stop_rports(struct fc_disc *disc)
* fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
* @sp: The sequence of the RSCN exchange
* @fp: The RSCN frame
* @disc: The discovery context of local port.
* @lport: The local port that the request will be sent on
*
* Locking Note: This function expects that the disc_mutex is locked
@ -342,9 +343,9 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
}
}
/**
/*
* fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
* @lport: The discovery context
* @disc: The discovery context
*
* Locking Note: This function expects that the disc_mutex is locked
* before it is called.
@ -376,9 +377,9 @@ err:
fc_disc_error(disc, NULL);
}
/**
/*
* fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
* @lport: The local port the GPN_FT was received on
* @disc: The discovery context
* @buf: The GPN_FT response buffer
* @len: The size of response buffer
*
@ -495,11 +496,11 @@ static void fc_disc_timeout(struct work_struct *work)
mutex_unlock(&disc->disc_mutex);
}
/**
/*
* fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
* @sp: The sequence that the GPN_FT response was received on
* @fp: The GPN_FT response frame
* @lp_arg: The discovery context
* @disc_arg: The discovery context
*
* Locking Note: This function is called without disc mutex held, and
* should do all its processing with the mutex held

View file

@ -615,7 +615,7 @@ err:
/**
* fc_fcp_send_data() - Send SCSI data to a target
* @fsp: The FCP packet the data is on
* @sp: The sequence the data is to be sent on
* @seq: The sequence the data is to be sent on
* @offset: The starting offset for this data request
* @seq_blen: The burst length for this data request
*
@ -1767,7 +1767,7 @@ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp)
fc_fcp_send_abort(fsp);
}
/**
/*
* fc_fcp_srr() - Send a SRR request (Sequence Retransmission Request)
* @fsp: The FCP packet the SRR is to be sent on
* @r_ctl: The R_CTL field for the SRR request
@ -1912,7 +1912,7 @@ static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport)
/**
* fc_queuecommand() - The queuecommand function of the SCSI template
* @cmd: The scsi_cmnd to be executed
* @sc_cmd: The scsi_cmnd to be executed
* @done: The callback function to be called when the scsi_cmnd is complete
*
* This is the i/o strategy routine, called by the SCSI layer. This routine

View file

@ -406,7 +406,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
/**
* fc_lport_recv_echo_req() - Handle received ECHO request
* @sp: The sequence in the ECHO exchange
* @fp: ECHO request frame
* @in_fp: ECHO request frame
* @lport: The local port recieving the ECHO
*
* Locking Note: The lport lock is expected to be held before calling
@ -448,7 +448,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
/**
* fc_lport_recv_rnid_req() - Handle received Request Node ID data request
* @sp: The sequence in the RNID exchange
* @fp: The RNID request frame
* @in_fp: The RNID request frame
* @lport: The local port recieving the RNID
*
* Locking Note: The lport lock is expected to be held before calling
@ -1205,9 +1205,10 @@ static void fc_lport_enter_scr(struct fc_lport *lport)
fc_lport_error(lport, NULL);
}
/**
/*
* fc_lport_enter_ns() - register some object with the name server
* @lport: Fibre Channel local port to register
* @state: local port state
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.
@ -1705,6 +1706,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
* @job: The BSG Passthrough job
* @lport: The local port sending the request
* @did: The destination port id
* @tov: The timeout period for the frame (in msecs)
*
* Locking Note: The lport lock is expected to be held before calling
* this routine.

View file

@ -109,6 +109,7 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
/**
* fc_rport_create() - Create a new remote port
* @lport: The local port this remote port will be associated with
* @port_id: The remote port ID to be created.
* @ids: The identifiers for the new remote port
*
* The remote port will start in the INIT state.

View file

@ -18,8 +18,8 @@
#endif
#include "pci-quirks.h"
#if defined(__VMKLNX__)
#include "../host/xhci/xhci-ext-caps.h"
#else
//#include "../host/xhci/xhci-ext-caps.h"
//#else
#include "xhci-ext-caps.h"
#endif

View file

@ -994,7 +994,7 @@ static inline int ata_id_is_cfa(const u16 *id)
/**
* ata_drive_40wire - Check if device is a 40 wire IDE drive
* @id: the pointer to IDENTIFY DEVICE data
* @dev_id: the pointer to IDENTIFY DEVICE data
*
* Check if the device is a compact flash device.
*
@ -1053,7 +1053,7 @@ static inline int atapi_id_dmadir(const u16 *dev_id)
/**
* ata_set_lba_range_entries - Construct TRIM command data buffer
* @_buffer: TRIM data buffer
* @buf_zie: data buffer size
* @buf_size: data buffer size
* @sector: starting sector to be TRIMed
* @count: number of sectors
*

View file

@ -41,6 +41,16 @@ struct fc_ct_req {
/**
* fill FC header fields in specified fc_frame
* @fp: fc frame where header will be placed.
* @r_ctl: pointer to FC header R_CTL.
* @did: FC destination ID.
* @sid: FC source ID.
* @type: pointer to FC-4 type.
* @f_ctl: pointer to FC header F_CTL.
* @parm_offset: parameter offset.
*
* RETURN VALUE:
* None.
*/
/* _VMKLNX_CODECHECK_: fc_fill_fc_hdr */
static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
@ -81,7 +91,12 @@ static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
/**
* fc_ct_hdr_fill- fills ct header and reset ct payload
* returns pointer to ct request.
* @fp: fc frame where ct header be placed.
* @op: CT opcode.
* @req_size: size of request frame.
*
* RETURN VALUE:
* pointer to ct request.
*/
static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
unsigned int op, size_t req_size)
@ -180,10 +195,13 @@ static inline int fc_ct_fill(struct fc_lport *lport,
return 0;
}
/**
/*
* fc_plogi_fill - Fill in plogi request frame
*
* @lport: local port.
* @fp: fc frame where plogi request frame be placed.
* @op: opcode.
*/
/* _VMKLNX_CODECHECK_: fc_plogi_fill */
static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
unsigned int op)
{
@ -214,8 +232,11 @@ static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
cp->cp_open_seq = 1;
}
/**
/*
* fc_flogi_fill - Fill in a flogi request frame.
*
* @lport: local port
* @fp: fc frame where flogi request frame be placed.
*/
static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -239,8 +260,11 @@ static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
sp->sp_features = htons(FC_SP_FT_NPIV);
}
/**
/*
* fc_fdisc_fill - Fill in a fdisc request frame.
*
* @lport: local port.
* @fp: fc frame where fdisc request frame be placed.
*/
static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -262,8 +286,11 @@ static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
}
/**
/*
* fc_logo_fill - Fill in a logo request frame.
*
* @lport: local port
* @fp: fc frame where logo request frame be placed.
*/
static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -276,8 +303,11 @@ static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
logo->fl_n_port_wwn = htonll(lport->wwpn);
}
/**
/*
* fc_rtv_fill - Fill in RTV (read timeout value) request frame.
*
* @lport: local port
* @fp: fc frame where RTV request frame be placed.
*/
static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -288,8 +318,11 @@ static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
rtv->rtv_cmd = ELS_RTV;
}
/**
/*
* fc_rec_fill - Fill in rec request frame
*
* @lport: local port
* @fp: fc frame where rec request frame be placed.
*/
static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -304,8 +337,12 @@ static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
rec->rec_rx_id = htons(ep->rxid);
}
/**
/*
* fc_prli_fill - Fill in prli request frame
*
* @lport: local port
* @fp: fc frame where prli request frame be placed.
*
*/
static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -324,8 +361,12 @@ static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
pp->spp.spp_params = htonl(lport->service_params);
}
/**
/*
* fc_scr_fill - Fill in a scr request frame.
*
* @lport: local port
* @fp: fc frame where scr request frame be placed.
*
*/
static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
{
@ -337,8 +378,18 @@ static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
scr->scr_reg_func = ELS_SCRF_FULL;
}
/**
/*
* fc_els_fill - Fill in an ELS request frame
* @lport: local port.
* @did: not in use.
* @fp: fc frame where ELS request frame be placed.
* @op: operation code.
* @r_ctl: pointer to ELS request R_CTL.
* @fh_type: pointer to ELS type.
*
* RETURN VALUE:
* 0 on success.
* -EINVAL on failed.
*/
/* _VMKLNX_CODECHECK_: fc_els_fill */
static inline int fc_els_fill(struct fc_lport *lport,

View file

@ -72,12 +72,15 @@
p[2] = ((v) & 0xFF); \
} while (0)
/**
/*
* enum fc_lport_state - Local port states
* @LPORT_ST_DISABLED: Disabled
* @LPORT_ST_FLOGI: Fabric login (FLOGI) sent
* @LPORT_ST_DNS: Waiting for name server remote port to become ready
* @LPORT_ST_RPN_ID: Register port name by ID (RPN_ID) sent
* @LPORT_ST_RNN_ID:
* @LPORT_ST_RSNN_NN:
* @LPORT_ST_RSPN_ID:
* @LPORT_ST_RFT_ID: Register Fibre Channel types by ID (RFT_ID) sent
* @LPORT_ST_RFF_ID: Register FC-4 Features by ID (RFF_ID) sent
* @LPORT_ST_SCR: State Change Register (SCR) sent
@ -194,7 +197,7 @@ struct fc_rport_libfc_priv {
unsigned int r_a_tov;
};
/**
/*
* struct fc_rport_priv - libfc remote port and discovery info
* @local_port: The associated local port
* @rport: The FC transport remote port
@ -212,6 +215,13 @@ struct fc_rport_libfc_priv {
* @r_a_tov: Resource allocation timeout value (in msec)
* @rp_mutex: The mutex that protects the remote port
* @retry_work: Handle for retries
* @event:
* @ops:
* @peers:
* @event_work:
* @sp_features:
* @spp_type:
* @supported_classes:
* @event_callback: Callback when READY, FAILED or LOGO states complete
*/
struct fc_rport_priv {
@ -304,7 +314,7 @@ struct fc_seq_els_data {
enum fc_els_rjt_explan explan;
};
/**
/*
* struct fc_fcp_pkt - FCP request structure (one for each scsi_cmnd request)
* @lp: The associated local port
* @state: The state of the I/O
@ -338,6 +348,8 @@ struct fc_seq_els_data {
* @seq_ptr: The sequence that will carry the SCSI command
* @recov_retry: Number of recovery retries
* @recov_seq: The sequence for REC or SRR
* @sg:
* @vmksgel:
*/
struct fc_fcp_pkt {
/* Housekeeping information */
@ -800,7 +812,7 @@ struct libfc_function_template {
* struct fc_disc - Discovery context
* @retry_count: Number of retries
* @pending: 1 if discovery is pending, 0 if not
* @requesting: 1 if discovery has been requested, 0 if not
* @requested: 1 if discovery has been requested, 0 if not
* @seq_count: Number of sequences used for discovery
* @buf_len: Length of the discovery buffer
* @disc_id: Discovery ID
@ -830,7 +842,7 @@ struct fc_disc {
enum fc_disc_event);
};
/**
/*
* struct fc_lport - Local port
* @host: The SCSI host associated with a local port
* @ema_list: Exchange manager anchor list
@ -864,6 +876,8 @@ struct fc_disc {
* @mfs: The maximum Fibre Channel payload size
* @max_retry_count: The maximum retry attempts
* @max_rport_retry_count: The maximum remote port retry attempts
* @link_speed:
* @link_supported_speeds:
* @lro_xid: The maximum XID for LRO
* @lso_max: The maximum large offload send size
* @fcts: FC-4 type mask

View file

@ -55,7 +55,7 @@ enum fip_state {
FIP_ST_ENABLED,
};
/**
/*
* struct fcoe_ctlr - FCoE Controller and FIP state
* @state: internal FIP state for network link and FIP or non-FIP mode.
* @mode: LLD-selected mode.
@ -74,12 +74,14 @@ enum fip_state {
* @user_mfs: configured maximum FC frame size, including FC header.
* @flogi_oxid: exchange ID of most recent fabric login.
* @flogi_count: number of FLOGI attempts in AUTO mode.
* @reset_req:
* @map_dest: use the FC_MAP mode for destination MAC addresses.
* @spma: supports SPMA server-provided MACs mode
* @send_ctlr_ka: need to send controller keep alive
* @send_port_ka: need to send port keep alives
* @dest_addr: MAC address of the selected FC forwarder.
* @ctl_src_addr: the native MAC address of our local port.
* @vlan_id:
* @send: LLD-supplied function to handle sending FIP Ethernet frames
* @update_mac: LLD-supplied function to handle changes to MAC addresses.
* @get_src_addr: LLD-supplied function to supply a source MAC address.
@ -132,7 +134,7 @@ struct fcoe_ctlr {
spinlock_t lock;
};
/**
/*
* struct fcoe_fcf - Fibre-Channel Forwarder
* @list: list linkage
* @time: system time (jiffies) when an advertisement was last received
@ -144,6 +146,7 @@ struct fcoe_ctlr {
* @pri: selection priority, smaller values are better
* @flags: flags received from advertisement
* @fka_period: keep-alive period, in jiffies
* @fd_flags:
*
* A Fibre-Channel Forwarder (FCF) is the entity on the Ethernet that
* passes FCoE frames on to an FC fabric. This structure represents

View file

@ -248,6 +248,8 @@ static inline int scsi_get_resid(struct scsi_cmnd *cmd)
* scsi_for_each_sg - Loop over scsi_cmd's SG list
* @cmd: a pointer to struct scsi_cmnd
* @nseg: number of elements in the list
* @sg: scatter-gather list
* @__i: index of sg element
*
* Loop over @cmd scsi_cmd's SG list.
*

View file

@ -108,17 +108,16 @@ static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth)
/**
* scsi_deactivate_tcq - turn off tag command queueing
* @SDpnt: device to turn off TCQ for
*
* Turns off tag command queueing
*
* ESX Deviation Notes:
* blk layer is not supported/affected.
* @sdev: SCSI Device to turn off TCQ for
* @depth: number of commands the low level driver can queue up in non-tagged mode.
*
* RETURN VALUE:
* None
*
* ESX Deviation Notes:
* blk layer is not supported/affected.
*/
/* _VMKLNX_CODECHECK_: scsi_deactivate_tcq */
/* _VMKLNX_CODECHECK_: scsi_deactivate_tcq*/
static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
{
#if !defined(__VMKLNX__)
@ -130,7 +129,7 @@ static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
/**
* scsi_populate_tag_msg - place a tag message in a buffer
* @SCpnt: pointer to the Scsi_Cmnd for the tag
* @cmd: pointer to the Scsi_Cmnd for the tag
* @msg: pointer to the area to place the tag
*
* Create the correct type of tag message for the
@ -190,14 +189,14 @@ static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
#endif
}
/**
/*
* scsi_find_tag - find a tagged command by device
* @SDpnt: pointer to the ScSI device
* @sdev: pointer to the SCSI device
* @tag: the tag number
*
* Notes:
* Only works with tags allocated by the generic blk layer.
**/
*/
static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
{
@ -212,7 +211,7 @@ static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
return sdev->current_cmnd;
}
/**
/*
* scsi_init_shared_tag_map - create a shared tag map
* @shost: the host to share the tag map among all devices
* @depth: the total depth of the map

View file

@ -502,14 +502,14 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
complete(eh_action);
}
/**
/*
* scsi_send_eh_cmnd - send a cmd to a device as part of error recovery.
* @scmd: SCSI Cmd to send.
* @timeout: Timeout for cmd.
*
* Return value:
* SUCCESS or FAILED or NEEDS_RETRY
**/
*/
static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
int cmnd_size, int timeout, int copy_sense)
{
@ -842,7 +842,7 @@ retry_tur:
}
}
/**
/*
* scsi_eh_abort_cmds - abort canceled commands.
* @shost: scsi host being recovered.
* @eh_done_q: list_head for processed commands.
@ -853,7 +853,7 @@ retry_tur:
* command that has timed out. if the command simply failed, it makes
* no sense to try and abort the command, since as far as the shost
* adapter is concerned, it isn't running.
**/
*/
static int scsi_eh_abort_cmds(struct list_head *work_q,
struct list_head *done_q)
{
@ -990,17 +990,17 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
}
/**
/*
* scsi_eh_bus_device_reset - send bdr if needed
* @shost: scsi host being recovered.
* @eh_done_q: list_head for processed commands.
* @done_q: list_head for processed commands.
*
* Notes:
* Try a bus device reset. still, look to see whether we have multiple
* devices that are jammed or not - if we have multiple devices, it
* makes no sense to try bus_device_reset - we really would need to try
* a bus_reset instead.
**/
*/
static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
@ -1115,11 +1115,11 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
return rtn;
}
/**
/*
* scsi_eh_bus_reset - send a bus reset
* @shost: scsi host being recovered.
* @eh_done_q: list_head for processed commands.
**/
*/
static int scsi_eh_bus_reset(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)
@ -1500,12 +1500,12 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
}
#if !defined(__VMKLNX__)
/**
/*
* scsi_eh_ready_devs - check device ready state and recover if not.
* @shost: host to be recovered.
* @eh_done_q: list_head for processed commands.
*
**/
*/
static void scsi_eh_ready_devs(struct Scsi_Host *shost,
struct list_head *work_q,
struct list_head *done_q)

View file

@ -2707,7 +2707,7 @@ __generic_unplug_device(request_queue_t *q, void *data)
VMKAPI_MODULE_CALL_VOID(BLOCK_GET_ID(dev), q->request_fn, q);
}
/**
/*
* generic_unplug_device - fire a request queue
* @q: The &request_queue_t in question
*
@ -2717,7 +2717,7 @@ __generic_unplug_device(request_queue_t *q, void *data)
* is still adding and merging requests on the queue. Once the queue
* gets unplugged, the request_fn defined for the queue is invoked and
* transfers started.
**/
*/
void
generic_unplug_device(request_queue_t *q, void *data)
{

View file

@ -179,6 +179,11 @@ LinuxPCILegacyIntrVectorSet(LinuxPCIDevExt *pciDevExt)
if (status != VMK_OK) {
VMKLNX_WARN("Could not allocate legacy PCI interrupt for device %s",
pciDevExt->linuxDev.dev.bus_id);
/*
* Ensure that the irq field is set to zero to indicate not to
* attempt to free the interrupt cookie.
*/
pciDevExt->linuxDev.irq = 0;
return;
}
@ -196,6 +201,17 @@ LinuxPCIIntrVectorFree(LinuxPCIDevExt *pciDevExt)
vmk_IntrCookie intrCookie;
VMK_ReturnStatus status;
/*
* Check whether the device even has a currently valid,
* allocated interrupt. We attempt to allocate a legacy interrupt
* on device-insert, but not all devices support legacy interrupts.
*/
if (pciDevExt->linuxDev.irq == 0) {
VMK_ASSERT(pciDevExt->linuxDev.msi_enabled == 0);
return;
}
/*
* Get the associated intrCookie for the irq.
*/
@ -494,14 +510,13 @@ LinuxPCIDeviceRemoved(vmk_PCIDevice vmkDev)
VMKAPI_MODULE_CALL_VOID(pciDevExt->moduleID, devres_release_all, &linuxDev->dev);
}
/* free the legacy interrupt setup during LinuxPCIDeviceInserted() */
LinuxPCIIntrVectorFree(pciDevExt);
linuxDev->driver = NULL;
linuxDev->dev.driver = NULL;
LinuxPCI_DeviceUnclaimed(pciDevExt);
quit:
/* free the legacy interrupt setup during LinuxPCIDeviceInserted() */
LinuxPCIIntrVectorFree(pciDevExt);
/*
* If device is physically removed, free up the structures. Otherwise,
@ -727,8 +742,8 @@ LinuxPCI_EnableMSI(struct pci_dev* dev)
VMK_ASSERT(pciDevExt->vmkDev);
/*
* Remove the previous legacy interrupt before requesting
* MSI interrupt.
* Remove the previous legacy interrupt, if it exists,
* before requesting MSI interrupt.
*/
LinuxPCIIntrVectorFree(pciDevExt);

View file

@ -155,24 +155,6 @@ static void scsi_offline_device(struct scsi_device *sdev);
static void vmklnx_scsi_update_lun_path(struct scsi_device *sdev, void *data);
static inline void vmklnx_init_scmd(struct scsi_cmnd *scmd, struct scsi_device *dev);
/**
**********************************************************************
* \globalfn scsi_host_alloc -- allocate a SCSI Host structure
*
* \param pointer to scsi host template
* \param additional size to be allocated as requested by the driver
* \return On Success pointer to newly allocated Scsi_Host structure
* \par Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
* This interface will assume a default value for
* Scsi_Host->dma_boundary to be 0 if the Scsi Host template does
* not specify a value for dma_boundary. This is different from
* the linux behavior which defaults to a 4G boundary in a similar
* situation.
* \sa None.
**********************************************************************
*/
/**
* scsi_host_alloc - allocate a Scsi_Host structure
* @sht: pointer to scsi host template
@ -316,18 +298,18 @@ failed_sh_alloc:
EXPORT_SYMBOL(scsi_host_alloc);
/**
**********************************************************************
* \internalfn scsi_setup_command_freelist -- Setup the command freelist
* Setup the command freelist
* @sh: host to allocate the freelist for
*
* \param shost - host to allocate the freelist for
* \return 0 on success
* \par Include:
* RETURN VALUE:
* 0 on success
*
* Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
*
* ESX Deviation Notes:
* Our scsi_cmnd cache also includes space for the maximally sized
* scatterlist array.
* \sa None.
**********************************************************************
*/
static int scsi_setup_command_freelist(struct Scsi_Host *sh)
{
@ -929,17 +911,6 @@ void vmklnx_scsi_register_poll_handler(struct Scsi_Host *sh,
}
EXPORT_SYMBOL(vmklnx_scsi_register_poll_handler);
/**
**********************************************************************
* \globalfn vmklnx_scsi_set_path_maxsectors --
* Set the max. transfer size for a path
*
* \param[in] sdev - the scsi_device struct representing the target path
* \param[in] max_sectors - the max. transfer size in 512-byte sectors
* \return None
*
**********************************************************************
*/
/**
* vmklnx_scsi_set_path_maxsectors - set the max transfer size for a path
* @sdev: a pointer to scsi_device struct representing the target path
@ -971,18 +942,15 @@ vmklnx_scsi_set_path_maxsectors(struct scsi_device *sdev,
EXPORT_SYMBOL(vmklnx_scsi_set_path_maxsectors);
/**
**********************************************************************
* \internalfn scsi_destroy_command_freelist -- Release the command freelist
* scsi_destroy_command_freelist -- Release the command freelist
* for a scsi host
* @sh: host that's freelist is going to be destroyed
*
* \param shost - host that's freelist is going to be destroyed
* \return None
* \par Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
* RETURN VALUE:
* None
* \sa None.
**********************************************************************
*
* Include:
* scsi/scsi_host.h
*/
static void
scsi_destroy_command_freelist(struct Scsi_Host *sh)
@ -1004,9 +972,8 @@ scsi_destroy_command_freelist(struct Scsi_Host *sh)
}
/*
* \sa All scanning functions needs PSA backend support. Will depend on
* All scanning functions needs PSA backend support. Will depend on
* completion of PR166189
**********************************************************************
*/
/**
* scsi_scan_host - issue wild card scan for the given SCSI host
@ -1097,8 +1064,6 @@ scsi_scan_host(struct Scsi_Host *sh)
EXPORT_SYMBOL(scsi_scan_host);
/*
*----------------------------------------------------------------------
*
* vmklnx_scsi_update_lun_path --
*
* Callback function used in scsi_scan_target which updates
@ -1109,8 +1074,6 @@ EXPORT_SYMBOL(scsi_scan_host);
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static void
vmklnx_scsi_update_lun_path(struct scsi_device *sdev, void *data)
@ -1212,18 +1175,14 @@ target_scan:
EXPORT_SYMBOL(scsi_scan_target);
/**
**********************************************************************
* \globalfn scsi_register -- Old style passive scsi registration
* Old style passive scsi registration
* @sht: scsi_host_template
* @privsize: private size
*
* \param scsi_host_template, privatesize
* \return None
* \par Include:
*
* \par ESX Deviation Notes:
*
* \sa None.
**********************************************************************
* RETURN VALUE:
* None
*/
/* _VMKLNX_CODECHECK_: scsi_register*/
struct Scsi_Host *
scsi_register(struct scsi_host_template *sht, int privsize)
{
@ -1245,17 +1204,11 @@ scsi_register(struct scsi_host_template *sht, int privsize)
}
/**
**********************************************************************
* \globalfn scsi_unregister -- Old style passive scsi unregistration
* Old style passive scsi unregistration
* @sh: scsi_host_template
*
* \param scsi_host_template, privatesize
* \return None
* \par Include:
*
* \par ESX Deviation Notes:
*
* \sa None.
**********************************************************************
* RETURN VALUE:
* None
*/
void
scsi_unregister(struct Scsi_Host *sh)
@ -1271,19 +1224,17 @@ scsi_unregister(struct Scsi_Host *sh)
}
/**
**********************************************************************
* \globalfn ScsiModifyQueueDepth -- Called by drivers to notify the vmkernel
* of the new queue Depth.
* Called by drivers to notify the vmkernel
* of the new queue Depth.
*
* \param arg - work queue payload containing vmkAdapter, channel, id, lun,
* @work: work queue payload containing vmkAdapter, channel, id, lun,
* queue depth
* \return None
* \par Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
*
* RETURN VALUE:
* None
* \sa None
**********************************************************************
*
* Include:
* scsi/scsi_host.h
*/
static void
vmklnx_scsi_modify_queue_depth(struct work_struct *work)
@ -1424,6 +1375,7 @@ EXPORT_SYMBOL(scsi_adjust_queue_depth);
* @channel: channel number
* @id: target id number
* @lun: logical unit number
* @hostdata: passed to scsi_alloc_sdev()
*
* Create new scsi device instance
*
@ -1708,6 +1660,11 @@ EXPORT_SYMBOL(scsi_bios_ptable);
/**
* scsi_partsize - non-operational function in release build.
* @buf: partition table, see scsi_bios_ptable
* @capacity: size of the disk in sector
* @cyls: cylinders
* @hds: heads
* @secs: sectors
*
* This is a non-operational function in release build, but can cause panic if being called in non-release mode.
*
@ -1733,18 +1690,20 @@ scsi_partsize(unsigned char *buf, unsigned long capacity,
EXPORT_SYMBOL(scsi_partsize);
/**
**********************************************************************
* \internalfn vmklnx_scsi_alloc_target_conditionally -- Allocate a target
/*
* vmklnx_scsi_alloc_target_conditionally -- Allocate a target
*
* \param parent, channel, id
* \return None
* \par Include:
* @parent: parent of the target (need not be a scsi host)
* @channel: target channel number (zero if no channels)
* @id: target id number
* @force_alloc_flag: if set, force to allocate scsi target.
* @old_target: output value. set as 1 if target already exists, 0 else.
*
* RETURN VALUE
* Pointer to an existing scsi target or a new scsi target.
*
* Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
**********************************************************************
*/
struct scsi_target *
vmklnx_scsi_alloc_target_conditionally(struct device *parent, int channel, uint id,
@ -1818,16 +1777,13 @@ alloc_and_return:
}
/**
**********************************************************************
* \internalfn scsi_alloc_target -- Allocate a new or find an existing target
* Allocate a new or find an existing target
* @parent: parent of the target (need not be a scsi host)
* @channel: target channel number (zero if no channels)
* @id: target id number
*
* \param parent, channel, id
* \return None
* \par Include:
* \par ESX Deviation Notes:
* Needs
* \sa None.
**********************************************************************
* RETURN VALUE:
* Pointer to scsi target
*/
struct scsi_target *
vmklnx_scsi_alloc_target(struct device *parent, int channel, uint id)
@ -1840,7 +1796,7 @@ EXPORT_SYMBOL(vmklnx_scsi_alloc_target);
EXPORT_SYMBOL_ALIASED(vmklnx_scsi_alloc_target, scsi_alloc_target);
/**
* scsi_alloc_target - Allocate a new or find an existing target
* Allocate a new or find an existing target
* @parent: parent device
* @channel: target id
* @id: target id
@ -1848,7 +1804,7 @@ EXPORT_SYMBOL_ALIASED(vmklnx_scsi_alloc_target, scsi_alloc_target);
* Allocate a new or find an existing target
*
* RETURN VALUE:
* scsi_target.
* pointer to scsi target.
*/
/* _VMKLNX_CODECHECK_: scsi_alloc_target */
struct scsi_target *
@ -1948,17 +1904,16 @@ scsi_alloc_target(struct device *parent, int channel, uint id)
}
/**
**********************************************************************
* \internalfn vmklnx_scsi_find_target -- Find a matching target
* Find a matching target
* @sh: scsi host
* @channel: target id
* @id: target id
*
* \param sh, channel, id
* \return None
* \par Include:
* RETURN VALUE:
* None
*
* Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
**********************************************************************
*/
struct scsi_target *
vmklnx_scsi_find_target(struct Scsi_Host *sh,
@ -1983,20 +1938,17 @@ vmklnx_scsi_find_target(struct Scsi_Host *sh,
EXPORT_SYMBOL(vmklnx_scsi_find_target);
/**
**********************************************************************
* \globalfn __scsi_device_lookup_by_target -- Find a matching device
/*
* Find a matching device
* for given target
*
* \param starget, lun
* \return None
* \par Include:
* RETURN VALUE:
* None
*
* Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
* \comments - Usually called from interrupt context
**********************************************************************
*
* comments - Usually called from interrupt context
*/
struct scsi_device *
__scsi_device_lookup_by_target(struct scsi_target *starget, uint lun)
@ -2012,7 +1964,7 @@ __scsi_device_lookup_by_target(struct scsi_target *starget, uint lun)
}
/**
* scsi_device_lookup_by_target - find a device given the target
* find a device given the target
* @starget: SCSI target pointer
* @lun: Logical Unit Number
*
@ -2046,20 +1998,20 @@ EXPORT_SYMBOL(scsi_device_lookup_by_target);
/**
**********************************************************************
* \globalfn scsi_alloc_sdev -- Allocate and set up a scsi device
* Allocate and set up a scsi device
* @starget: which target to allocate a scsi_device for
* @lun: which lun
* @hostdata: usually NULL and set by ->slave_alloc instead
*
* \param starget, lun, hostdata
* \return On failure to alloc sdev, return NULL
* RETURN VALUE:
* return On failure to alloc sdev, return NULL
* On other failures, return ERR_PTR(-errno)
* On Success, return pointer to sdev (which fails IF_ERR)
* \par Include:
*
* Include:
* scsi/scsi_device.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
* \comments - Gets the device ready for IO
**********************************************************************
*
* comments - Gets the device ready for IO
*/
struct scsi_device *
scsi_alloc_sdev(struct scsi_target *starget, unsigned int lun, void *hostdata)
@ -2181,18 +2133,16 @@ out_device_del:
}
/**
**********************************************************************
* \globalfn scsi_destroy_sdev -- Destroy a scsi device
* scsi_destroy_sdev -- Destroy a scsi device
* @sdev: sdevice
*
* \param sdevice
* \return Pointer to sdev
* \par Include:
* RETURN VALUE:
* Pointer to sdev
*
* Include:
* scsi/scsi_device.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
* \comments - Removes from all the lists as well
**********************************************************************
*
* comments - Removes from all the lists as well
*/
void
scsi_destroy_sdev(struct scsi_device *sdev)
@ -2211,19 +2161,20 @@ scsi_destroy_sdev(struct scsi_device *sdev)
}
/**
**********************************************************************
* \globalfn __scsi_device_lookup -- Look up for a scsi device given BTL
/*
* __scsi_device_lookup -- Look up for a scsi device given BTL
* @sh: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
* @id: SCSI target number (physical unit number)
* @lun: SCSI Logical Unit Number
*
* \param sh, channel, id, lun
* \return Pointer to sdev
* \par Include:
* RETURN VALUE:
* Pointer to scsi device
*
* Include:
* scsi/scsi_device.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
* \comments - Called from IRQ context or with lock held
**********************************************************************
*
* comments - Called from IRQ context or with lock held
*/
struct scsi_device *
__scsi_device_lookup(struct Scsi_Host *sh, uint channel, uint id, uint lun)
@ -2272,18 +2223,16 @@ EXPORT_SYMBOL(scsi_device_lookup);
/**
**********************************************************************
* \globalfn __scsi_get_command -- Return a Scsi_Cmnd
* __scsi_get_command -- Return a Scsi_Cmnd
*
* \param sh, mask
* \return Pointer to sdev
* \par Include:
* @sh: scsi host
* @gfp_mask: allocator flags
*
* RETURN VALUE:
* Pointer to sdev
*
* Include:
* scsi/scsi_device.h
* \par ESX Deviation Notes:
* Needs
* \sa None.
* \comments -
**********************************************************************
*/
struct scsi_cmnd *
__scsi_get_command(struct Scsi_Host *sh, gfp_t gfp_mask)
@ -2925,17 +2874,15 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
EXPORT_SYMBOL(scsi_host_lookup);
/**
**********************************************************************
* \internalfn scsi_forget_host -- Notify all LUNs that a host is going down
* scsi_forget_host -- Notify all LUNs that a host is going down
*
* \param shost - host that is being removed
* \return None
* \par Include:
* scsi/scsi_host.h
* \par ESX Deviation Notes:
* @sh: host that is being removed
*
* RETURN VALUE:
* None
* \sa None.
**********************************************************************
*
* Include:
* scsi/scsi_host.h
*/
static void scsi_forget_host(struct Scsi_Host *sh)
{
@ -3069,7 +3016,7 @@ EXPORT_SYMBOL(scsi_execute_req);
* @timeout: command timeout
* @retries: number of retries before failing
* @data: returns a structure abstracting the mode header data
* @sense: place to put sense data (or NULL if no sense to be collected).
* @sshdr: place to put sense data (or NULL if no sense to be collected).
* must be SCSI_SENSE_BUFFERSIZE big.
*
* Returns zero if unsuccessful, or the header offset (either 4
@ -3169,19 +3116,6 @@ retry:
return result;
}
/**
**********************************************************************
* \globalfn scsi_is_target_device -- Check if this is target type device
*
* \param device struct associated with this target
* \return 0 if not a valid device
* \par Include:
* scsi/scsi_device.h
* \par ESX Deviation Notes:
* None
* \sa None.
**********************************************************************
*/
/**
* scsi_is_target_device - Check if this is target type device
* @dev: device struct associated with this target
@ -3597,17 +3531,14 @@ scsi_rescan_device(struct device *dev)
EXPORT_SYMBOL(scsi_rescan_device);
/**
**************************************************************************
* \globalfn scsi_device_set_state - Take the given device through the device
* scsi_device_set_state - Take the given device through the device
* state model.
* \param sdev scsi device to change the state of.
* \param state state to change to.
* \return zero if unsuccessful or an error if the requested transition
* @sdev: scsi device to change the state of.
* @state: state to change to.
*
* RETURN VALUE:
* return zero if unsuccessful or an error if the requested transition
* is illegal.
* \par ESX Deviation Notes:
* None
* \sa None
**************************************************************************
**/
/**
* scsi_device_set_state - Set scsi state to the given scsi device
@ -3633,14 +3564,11 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
EXPORT_SYMBOL(scsi_device_set_state);
/**
**************************************************************************
* \globalfn vmklnx_get_vmhba_name - Provide the vmhba name
* \param shost - Scsi_Host for the adapter
* \return vmhba Name
* \par ESX Deviation Notes:
* None
* \sa None
**************************************************************************
* vmklnx_get_vmhba_name - Provide the vmhba name
* @sh: Scsi_Host for the adapter
*
* RETURN VALUE:
* vmhba Name
**/
char *
vmklnx_get_vmhba_name(struct Scsi_Host *sh)
@ -3662,8 +3590,6 @@ vmklnx_get_vmhba_name(struct Scsi_Host *sh)
EXPORT_SYMBOL(vmklnx_get_vmhba_name);
/*
*----------------------------------------------------------------------
*
* vmklnx_scsi_free_host_resources --
*
* Frees the common host resources
@ -3673,8 +3599,6 @@ EXPORT_SYMBOL(vmklnx_get_vmhba_name);
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static void
vmklnx_scsi_free_host_resources(struct Scsi_Host *sh)
@ -3697,8 +3621,6 @@ vmklnx_scsi_free_host_resources(struct Scsi_Host *sh)
/*
*----------------------------------------------------------------------
*
* scsi_host_dev_release --
*
* This function is called when the ref count on the adapter goes to zero
@ -3710,8 +3632,6 @@ vmklnx_scsi_free_host_resources(struct Scsi_Host *sh)
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static void scsi_host_dev_release(struct device *dev)
{
@ -3780,8 +3700,6 @@ vmklnx_destroy_adapter_tls(struct vmklnx_ScsiAdapter *vmklnx26ScsiAdapter)
}
/*
*----------------------------------------------------------------------
*
* vmklnx_scsi_unregister_host --
*
* This function is called from a WQ. This fn unregisters ourselves
@ -3792,8 +3710,6 @@ vmklnx_destroy_adapter_tls(struct vmklnx_ScsiAdapter *vmklnx26ScsiAdapter)
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static void
vmklnx_scsi_unregister_host(struct work_struct *work)
@ -3853,8 +3769,6 @@ vmklnx_scsi_unregister_host(struct work_struct *work)
/*
*----------------------------------------------------------------------
*
* scsi_target_dev_release --
*
* This function is called when the ref count on the target goes to zero
@ -3865,8 +3779,6 @@ vmklnx_scsi_unregister_host(struct work_struct *work)
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static void scsi_target_dev_release(struct device *dev)
{
@ -3896,8 +3808,6 @@ static void scsi_target_dev_release(struct device *dev)
}
/*
*----------------------------------------------------------------------
*
* scsi_device_dev_release --
*
* This function is called when the ref count on the device goes to zero
@ -3909,8 +3819,6 @@ static void scsi_target_dev_release(struct device *dev)
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
static void scsi_device_dev_release(struct device *dev)
{
@ -3990,7 +3898,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
/**
* scsi_req_abort_cmd -- Request command recovery for the specified command
* cmd: pointer to the SCSI command of interest
* @cmd: pointer to the SCSI command of interest
*
* This function requests that SCSI Core start recovery for the
* command by deleting the timer and adding the command to the eh
@ -3998,6 +3906,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
* implement their own error recovery MAY ignore the timeout event if
* they generated scsi_req_abort_cmd.
**/
/* _VMKLNX_CODECHECK_: scsi_req_abort_cmd*/
void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
{
VMK_ASSERT(vmk_PreemptionIsEnabled() == VMK_FALSE);
@ -4023,6 +3932,7 @@ void __scsi_done(struct scsi_cmnd *cmd)
* Returns zero if successful or an error if the requested
* transition is illegal.
**/
/* _VMKLNX_CODECHECK_: csi_host_set_state*/
int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
{
VMK_ASSERT(vmk_PreemptionIsEnabled() == VMK_FALSE);
@ -4078,17 +3988,12 @@ vmklnx_scsi_target_offline(struct device *dev)
EXPORT_SYMBOL(vmklnx_scsi_target_offline);
EXPORT_SYMBOL_ALIASED(vmklnx_scsi_target_offline, scsi_target_offline);
/**
**********************************************************************
* \globalfn scsi_offline_device -- Mark the device offline
/*
* scsi_offline_device -- Mark the device offline
* @sdev: scsi device
*
* \param sh
* \return None
* \par Include:
* \par ESX Deviation Notes:
* RETURN VALUE:
* None
* \sa None
**********************************************************************
*/
static void
scsi_offline_device(struct scsi_device *sdev)
@ -4146,19 +4051,18 @@ scsi_offline_device(struct scsi_device *sdev)
}
/**
**********************************************************************
* \globalfn vmklnx_scsi_get_num_ioqueue -- get num of queues to create
*
* \param Maximum queues adapter can create
* \return Number of queues to be created, returns 0 for no additional
* queues in adapter
* \par Include:
* \par ESX Deviation Notes:
* get num of queues to create
* @maxQueue: Maximum queues adapter can create
*
* RETURN VALUE:
* return Number of queues to be created, returns 0 for no additional
* queues in adapter
*
* ESX Deviation Notes:
* ESX specific API to query VMKernel for the number of queues to
* be created
* \sa None
**********************************************************************
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_get_num_ioqueue*/
int
vmklnx_scsi_get_num_ioqueue(unsigned int maxQueue)
{
@ -4171,19 +4075,19 @@ vmklnx_scsi_get_num_ioqueue(unsigned int maxQueue)
EXPORT_SYMBOL(vmklnx_scsi_get_num_ioqueue);
/**
**********************************************************************
* \globalfn vmklnx_scsi_get_cmd_ioqueue_handle -- returns queue handle
*
* \param scsi_cmd, sh
* \return ioqueue handle
* \par Include:
* \par ESX Deviation Notes:
* returns queue handle
* @cmd: scsi command
* @sh: scsi host
*
* RETURN VALUE:
* ioqueue handle
*
* Deviation Notes:
* ESX specific API to query VMKernel for the ioqueues to be used
* to issue the given scsi command
* None
* \sa None
**********************************************************************
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_get_cmd_ioqueue_handle*/
void *
vmklnx_scsi_get_cmd_ioqueue_handle(struct scsi_cmnd *cmd,
struct Scsi_Host *sh)
@ -4204,21 +4108,20 @@ vmklnx_scsi_get_cmd_ioqueue_handle(struct scsi_cmnd *cmd,
EXPORT_SYMBOL(vmklnx_scsi_get_cmd_ioqueue_handle);
/**
**********************************************************************
* \globalfn vmklnx_scsi_register_ioqueue-- pass queue info to vmkernel
* vmklnx_scsi_register_ioqueue-- pass queue info to vmkernel.
* ESX specific API to register all the ioqueues in the adapter
* with VMKernel. For each ioqueue the driver should provide the
* handle and interrupt vector. The handle will be returned by
* vmkernel when vmklnx_scsi_get_cmd_ioqueue_handle() is invoked
* to select queue for a scsi_cmd.
* @sh: scsi host
* @numIoQueue: Number of I/O queues
* @q_info: scsi_ioqueue_info for each queue
*
* \param sh, Number of I/O queues, scsi_ioqueue_info for each queue
* \return zero if successful, error code otherwise
* \par Include:
* \par ESX Deviation Notes:
* ESX specific API to register all the ioqueues in the adapter
* with VMKernel. For each ioqueue the driver should provide the
* handle and interrupt vector. The handle will be returned by
* vmkernel when vmklnx_scsi_get_cmd_ioqueue_handle() is invoked
* to select queue for a scsi_cmd
* \sa None
**********************************************************************
* RETURN VALUE:
* return zero if successful, error code otherwise
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_register_ioqueue*/
int
vmklnx_scsi_register_ioqueue(struct Scsi_Host *sh, unsigned int numIoQueue,
struct vmklnx_scsi_ioqueue_info q_info[])
@ -4361,8 +4264,6 @@ SCSILinux_InitLLD(void)
}
/*
*----------------------------------------------------------------------
*
* SCSILinux_CleanupLLD
*
* Entry point for SCSI LLD-specific teardown.
@ -4373,8 +4274,6 @@ SCSILinux_InitLLD(void)
*
* Side effects:
* Cleans up SCSI LLD log.
*
*----------------------------------------------------------------------
*/
void
SCSILinux_CleanupLLD(void)
@ -4384,7 +4283,7 @@ SCSILinux_CleanupLLD(void)
/**
* scsi_device_reprobe - Rediscover device status by reprobing if needed
* sdev: Pointer to scsi_device which needs status update
* @sdev: Pointer to scsi_device which needs status update
*
* This function will either hide a device which doesn't need exposure to upper
* layers anymore or will initiate a scan to rediscover new devices on the
@ -4418,16 +4317,14 @@ EXPORT_SYMBOL(scsi_device_reprobe);
/**
***********************************************************************
* vmklnx_scsi_cmd_get_sensedata - Get sense data length from SCSI cmd
* scmd: SCSI command
* buf: Buffer that will contain sense data
* bufLen: Length of the sense buffer
* @scmd: SCSI command
* @buf: Buffer that will contain sense data
* @bufLen: Length of the sense buffer
*
* Command is identified by scmd. The buffer buf is filled with sense data.
* The length of the input buffer is passed through bufLen.
*
**********************************************************************
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_cmd_get_sensedata */
int
@ -4441,19 +4338,16 @@ vmklnx_scsi_cmd_get_sensedata(struct scsi_cmnd *scmd,
EXPORT_SYMBOL(vmklnx_scsi_cmd_get_sensedata);
/**
***********************************************************************
* vmklnx_scsi_cmd_set_sensedata - Set sense data of SCSI cmd
* buf: Buffer that contains sense data to set
* scmd: SCSI command
* bufLen: Number of bytes to copy
* @buf: Buffer that contains sense data to set
* @scmd: SCSI command
* @bufLen: Number of bytes to copy
*
* Command is identified by scmd. The number of bytes to copy from buf
* is passed as bufLen. If the number of bytes to copy is less than the
* sense buffer size of SCSI cmd(obtained by calling
* vmklnx_scsi_cmd_get_supportedsensedata_size), the remaining bytes in
* SCSI cmd's sense buffer are set to 0.
*
**********************************************************************
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_cmd_set_sensedata */
int
@ -4467,13 +4361,11 @@ vmklnx_scsi_cmd_set_sensedata(uint8_t *buf,
EXPORT_SYMBOL(vmklnx_scsi_cmd_set_sensedata);
/**
***********************************************************************
* vmklnx_scsi_cmd_clear_sensedata - Clear sense data of SCSI cmd
* scmd: SCSI command
* @scmd: SCSI command
*
* Command is identified by scmd.
*
**********************************************************************
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_cmd_clear_sensedata */
int
@ -4484,10 +4376,8 @@ vmklnx_scsi_cmd_clear_sensedata(struct scsi_cmnd *scmd)
EXPORT_SYMBOL(vmklnx_scsi_cmd_clear_sensedata);
/**
***********************************************************************
* vmklnx_scsi_cmd_get_supportedsensedata_size - Get scmd's sense buffer size
*
**********************************************************************
*/
/* _VMKLNX_CODECHECK_: vmklnx_scsi_cmd_get_supportedsensedata_size */
int

File diff suppressed because it is too large Load diff

View file

@ -1617,6 +1617,14 @@ FcLinuxPortAttributes(void *clientData, vmk_uint32 portId, vmk_FcPortAttributes
return VMK_NOT_FOUND;
}
if (ft->get_host_port_id) {
VMKAPI_MODULE_CALL_VOID(SCSI_GET_MODULE_ID(shost), ft->get_host_port_id, shost);
}
if (ft->get_host_speed) {
VMKAPI_MODULE_CALL_VOID(SCSI_GET_MODULE_ID(shost), ft->get_host_speed, shost);
}
lport = shost_priv(shost);
memset(portAttrib, 0, sizeof(vmk_FcPortAttributes));