Commit a16af2ff authored by David S. Miller's avatar David S. Miller

Merge branch 'intel'

Jeff Kirsher says:

====================
This series contains updates to e1000e and igb.  Most notably is the
added timestamp support in e1000e and additional software timestamp
support in igb.  As well as, the added thermal data support and SR-IOV
configuration support in igb.

v2- dropped the following patches from the previous 14 patch series
because changes were requested from the community:
  e1000e: add support for IEEE-1588 PTP
  igb: Report L4 Rx hash via skb->l4_rxhash
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 887c95cc ba59814b
...@@ -94,6 +94,8 @@ config IGB ...@@ -94,6 +94,8 @@ config IGB
tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
depends on PCI depends on PCI
select PTP_1588_CLOCK select PTP_1588_CLOCK
select I2C
select I2C_ALGOBIT
---help--- ---help---
This driver supports Intel(R) 82575/82576 gigabit ethernet family of This driver supports Intel(R) 82575/82576 gigabit ethernet family of
adapters. For more information on how to identify your adapter, go adapters. For more information on how to identify your adapter, go
...@@ -112,6 +114,17 @@ config IGB ...@@ -112,6 +114,17 @@ config IGB
To compile this driver as a module, choose M here. The module To compile this driver as a module, choose M here. The module
will be called igb. will be called igb.
config IGB_HWMON
bool "Intel(R) PCI-Express Gigabit adapters HWMON support"
default y
depends on IGB && HWMON && !(IGB=y && HWMON=m)
---help---
Say Y if you want to expose thermal sensor data on Intel devices.
Some of our devices contain thermal sensors, both external and internal.
This data is available via the hwmon sysfs interface and exposes
the onboard sensors.
config IGB_DCA config IGB_DCA
bool "Direct Cache Access (DCA) Support" bool "Direct Cache Access (DCA) Support"
default y default y
......
...@@ -2044,6 +2044,7 @@ const struct e1000_info e1000_82574_info = { ...@@ -2044,6 +2044,7 @@ const struct e1000_info e1000_82574_info = {
| FLAG_HAS_MSIX | FLAG_HAS_MSIX
| FLAG_HAS_JUMBO_FRAMES | FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL | FLAG_HAS_WOL
| FLAG_HAS_HW_TIMESTAMP
| FLAG_APME_IN_CTRL3 | FLAG_APME_IN_CTRL3
| FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT | FLAG_HAS_AMT
...@@ -2065,6 +2066,7 @@ const struct e1000_info e1000_82583_info = { ...@@ -2065,6 +2066,7 @@ const struct e1000_info e1000_82583_info = {
.mac = e1000_82583, .mac = e1000_82583,
.flags = FLAG_HAS_HW_VLAN_FILTER .flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_WOL | FLAG_HAS_WOL
| FLAG_HAS_HW_TIMESTAMP
| FLAG_APME_IN_CTRL3 | FLAG_APME_IN_CTRL3
| FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT | FLAG_HAS_AMT
......
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */
#define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_CE 0x01000000
#define E1000_RXDEXT_STATERR_SE 0x02000000 #define E1000_RXDEXT_STATERR_SE 0x02000000
#define E1000_RXDEXT_STATERR_SEQ 0x04000000 #define E1000_RXDEXT_STATERR_SEQ 0x04000000
...@@ -318,6 +319,7 @@ ...@@ -318,6 +319,7 @@
#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ #define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
/* Transmit Control */ /* Transmit Control */
#define E1000_TCTL_EN 0x00000002 /* enable Tx */ #define E1000_TCTL_EN 0x00000002 /* enable Tx */
...@@ -383,6 +385,9 @@ ...@@ -383,6 +385,9 @@
#define E1000_KABGTXD_BGSQLBIAS 0x00050000 #define E1000_KABGTXD_BGSQLBIAS 0x00050000
/* Low Power IDLE Control */
#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */
/* PBA constants */ /* PBA constants */
#define E1000_PBA_8K 0x0008 /* 8KB */ #define E1000_PBA_8K 0x0008 /* 8KB */
#define E1000_PBA_16K 0x0010 /* 16KB */ #define E1000_PBA_16K 0x0010 /* 16KB */
...@@ -533,6 +538,18 @@ ...@@ -533,6 +538,18 @@
#define E1000_RXCW_C 0x20000000 /* Receive config */ #define E1000_RXCW_C 0x20000000 /* Receive config */
#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
#define E1000_TSYNCRXCTL_TYPE_ALL 0x08
#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
#define E1000_TIMINCA_INCPERIOD_SHIFT 24
#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF
/* PCI Express Control */ /* PCI Express Control */
#define E1000_GCR_RXD_NO_SNOOP 0x00000001 #define E1000_GCR_RXD_NO_SNOOP 0x00000001
#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
...@@ -799,6 +816,33 @@ ...@@ -799,6 +816,33 @@
/* BME1000 PHY Specific Control Register */ /* BME1000 PHY Specific Control Register */
#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ #define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */
/* PHY Low Power Idle Control */
#define I82579_LPI_CTRL PHY_REG(772, 20)
#define I82579_LPI_CTRL_100_ENABLE 0x2000
#define I82579_LPI_CTRL_1000_ENABLE 0x4000
#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80
/* Extended Management Interface (EMI) Registers */
#define I82579_EMI_ADDR 0x10
#define I82579_EMI_DATA 0x11
#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */
#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */
#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */
#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */
#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */
#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */
#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */
#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */
#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */
#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */
#define PHY_PAGE_SHIFT 5 #define PHY_PAGE_SHIFT 5
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ #define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#include <linux/pci-aspm.h> #include <linux/pci-aspm.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
#include "hw.h" #include "hw.h"
...@@ -353,6 +355,7 @@ struct e1000_adapter { ...@@ -353,6 +355,7 @@ struct e1000_adapter {
u64 gorc_old; u64 gorc_old;
u32 alloc_rx_buff_failed; u32 alloc_rx_buff_failed;
u32 rx_dma_failed; u32 rx_dma_failed;
u32 rx_hwtstamp_cleared;
unsigned int rx_ps_pages; unsigned int rx_ps_pages;
u16 rx_ps_bsize0; u16 rx_ps_bsize0;
...@@ -402,6 +405,14 @@ struct e1000_adapter { ...@@ -402,6 +405,14 @@ struct e1000_adapter {
u16 tx_ring_count; u16 tx_ring_count;
u16 rx_ring_count; u16 rx_ring_count;
struct hwtstamp_config hwtstamp_config;
struct delayed_work systim_overflow_work;
struct sk_buff *tx_hwtstamp_skb;
struct work_struct tx_hwtstamp_work;
spinlock_t systim_lock; /* protects SYSTIML/H regsters */
struct cyclecounter cc;
struct timecounter tc;
}; };
struct e1000_info { struct e1000_info {
...@@ -416,6 +427,38 @@ struct e1000_info { ...@@ -416,6 +427,38 @@ struct e1000_info {
const struct e1000_nvm_operations *nvm_ops; const struct e1000_nvm_operations *nvm_ops;
}; };
/* The system time is maintained by a 64-bit counter comprised of the 32-bit
* SYSTIMH and SYSTIML registers. How the counter increments (and therefore
* its resolution) is based on the contents of the TIMINCA register - it
* increments every incperiod (bits 31:24) clock ticks by incvalue (bits 23:0).
* For the best accuracy, the incperiod should be as small as possible. The
* incvalue is scaled by a factor as large as possible (while still fitting
* in bits 23:0) so that relatively small clock corrections can be made.
*
* As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of
* INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n)
* bits to count nanoseconds leaving the rest for fractional nonseconds.
*/
#define INCVALUE_96MHz 125
#define INCVALUE_SHIFT_96MHz 17
#define INCPERIOD_SHIFT_96MHz 2
#define INCPERIOD_96MHz (12 >> INCPERIOD_SHIFT_96MHz)
#define INCVALUE_25MHz 40
#define INCVALUE_SHIFT_25MHz 18
#define INCPERIOD_25MHz 1
/* Another drawback of scaling the incvalue by a large factor is the
* 64-bit SYSTIM register overflows more quickly. This is dealt with
* by simply reading the clock before it overflows.
*
* Clock ns bits Overflows after
* ~~~~~~ ~~~~~~~ ~~~~~~~~~~~~~~~
* 96MHz 47-bit 2^(47-INCPERIOD_SHIFT_96MHz) / 10^9 / 3600 = 9.77 hrs
* 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours
*/
#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4)
/* hardware capability, feature, and workaround flags */ /* hardware capability, feature, and workaround flags */
#define FLAG_HAS_AMT (1 << 0) #define FLAG_HAS_AMT (1 << 0)
#define FLAG_HAS_FLASH (1 << 1) #define FLAG_HAS_FLASH (1 << 1)
...@@ -431,7 +474,7 @@ struct e1000_info { ...@@ -431,7 +474,7 @@ struct e1000_info {
#define FLAG_HAS_SMART_POWER_DOWN (1 << 11) #define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
#define FLAG_IS_QUAD_PORT_A (1 << 12) #define FLAG_IS_QUAD_PORT_A (1 << 12)
#define FLAG_IS_QUAD_PORT (1 << 13) #define FLAG_IS_QUAD_PORT (1 << 13)
/* reserved bit14 */ #define FLAG_HAS_HW_TIMESTAMP (1 << 14)
#define FLAG_APME_IN_WUC (1 << 15) #define FLAG_APME_IN_WUC (1 << 15)
#define FLAG_APME_IN_CTRL3 (1 << 16) #define FLAG_APME_IN_CTRL3 (1 << 16)
#define FLAG_APME_CHECK_PORT_B (1 << 17) #define FLAG_APME_CHECK_PORT_B (1 << 17)
...@@ -463,6 +506,7 @@ struct e1000_info { ...@@ -463,6 +506,7 @@ struct e1000_info {
#define FLAG2_NO_DISABLE_RX (1 << 10) #define FLAG2_NO_DISABLE_RX (1 << 10)
#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11) #define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11)
#define FLAG2_DFLT_CRC_STRIPPING (1 << 12) #define FLAG2_DFLT_CRC_STRIPPING (1 << 12)
#define FLAG2_CHECK_RX_HWTSTAMP (1 << 13)
#define E1000_RX_DESC_PS(R, i) \ #define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
...@@ -659,6 +703,7 @@ extern s32 e1000_check_polarity_ife(struct e1000_hw *hw); ...@@ -659,6 +703,7 @@ extern s32 e1000_check_polarity_ife(struct e1000_hw *hw);
extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); extern s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
extern s32 e1000_check_polarity_igp(struct e1000_hw *hw); extern s32 e1000_check_polarity_igp(struct e1000_hw *hw);
extern bool e1000_check_phy_82574(struct e1000_hw *hw); extern bool e1000_check_phy_82574(struct e1000_hw *hw);
extern s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data);
static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{ {
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/mdio.h>
#include "e1000.h" #include "e1000.h"
...@@ -107,6 +108,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { ...@@ -107,6 +108,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
E1000_STAT("dropped_smbus", stats.mgpdc), E1000_STAT("dropped_smbus", stats.mgpdc),
E1000_STAT("rx_dma_failed", rx_dma_failed), E1000_STAT("rx_dma_failed", rx_dma_failed),
E1000_STAT("tx_dma_failed", tx_dma_failed), E1000_STAT("tx_dma_failed", tx_dma_failed),
E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
}; };
#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
...@@ -2050,6 +2052,159 @@ static int e1000_get_rxnfc(struct net_device *netdev, ...@@ -2050,6 +2052,159 @@ static int e1000_get_rxnfc(struct net_device *netdev,
} }
} }
static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
u16 cap_addr, adv_addr, lpa_addr, pcs_stat_addr, phy_data, lpi_ctrl;
u32 status, ret_val;
if (!(adapter->flags & FLAG_IS_ICH) ||
!(adapter->flags2 & FLAG2_HAS_EEE))
return -EOPNOTSUPP;
switch (hw->phy.type) {
case e1000_phy_82579:
cap_addr = I82579_EEE_CAPABILITY;
adv_addr = I82579_EEE_ADVERTISEMENT;
lpa_addr = I82579_EEE_LP_ABILITY;
pcs_stat_addr = I82579_EEE_PCS_STATUS;
break;
case e1000_phy_i217:
cap_addr = I217_EEE_CAPABILITY;
adv_addr = I217_EEE_ADVERTISEMENT;
lpa_addr = I217_EEE_LP_ABILITY;
pcs_stat_addr = I217_EEE_PCS_STATUS;
break;
default:
return -EOPNOTSUPP;
}
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return -EBUSY;
/* EEE Capability */
ret_val = e1000_read_emi_reg_locked(hw, cap_addr, &phy_data);
if (ret_val)
goto release;
edata->supported = mmd_eee_cap_to_ethtool_sup_t(phy_data);
/* EEE Advertised */
ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &phy_data);
if (ret_val)
goto release;
edata->advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
/* EEE Link Partner Advertised */
ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data);
if (ret_val)
goto release;
edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
/* EEE PCS Status */
ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data);
if (hw->phy.type == e1000_phy_82579)
phy_data <<= 8;
release:
hw->phy.ops.release(hw);
if (ret_val)
return -ENODATA;
e1e_rphy(hw, I82579_LPI_CTRL, &lpi_ctrl);
status = er32(STATUS);
/* Result of the EEE auto negotiation - there is no register that
* has the status of the EEE negotiation so do a best-guess based
* on whether both Tx and Rx LPI indications have been received or
* base it on the link speed, the EEE advertised speeds on both ends
* and the speeds on which EEE is enabled locally.
*/
if (((phy_data & E1000_EEE_TX_LPI_RCVD) &&
(phy_data & E1000_EEE_RX_LPI_RCVD)) ||
((status & E1000_STATUS_SPEED_100) &&
(edata->advertised & ADVERTISED_100baseT_Full) &&
(edata->lp_advertised & ADVERTISED_100baseT_Full) &&
(lpi_ctrl & I82579_LPI_CTRL_100_ENABLE)) ||
((status & E1000_STATUS_SPEED_1000) &&
(edata->advertised & ADVERTISED_1000baseT_Full) &&
(edata->lp_advertised & ADVERTISED_1000baseT_Full) &&
(lpi_ctrl & I82579_LPI_CTRL_1000_ENABLE)))
edata->eee_active = true;
edata->eee_enabled = !hw->dev_spec.ich8lan.eee_disable;
edata->tx_lpi_enabled = true;
edata->tx_lpi_timer = er32(LPIC) >> E1000_LPIC_LPIET_SHIFT;
return 0;
}
static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct ethtool_eee eee_curr;
s32 ret_val;
if (!(adapter->flags & FLAG_IS_ICH) ||
!(adapter->flags2 & FLAG2_HAS_EEE))
return -EOPNOTSUPP;
ret_val = e1000e_get_eee(netdev, &eee_curr);
if (ret_val)
return ret_val;
if (eee_curr.advertised != edata->advertised) {
e_err("Setting EEE advertisement is not supported\n");
return -EINVAL;
}
if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
e_err("Setting EEE tx-lpi is not supported\n");
return -EINVAL;
}
if (eee_curr.tx_lpi_timer != edata->tx_lpi_timer) {
e_err("Setting EEE Tx LPI timer is not supported\n");
return -EINVAL;
}
if (hw->dev_spec.ich8lan.eee_disable != !edata->eee_enabled) {
hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled;
/* reset the link */
if (netif_running(netdev))
e1000e_reinit_locked(adapter);
else
e1000e_reset(adapter);
}
return 0;
}
static int e1000e_get_ts_info(struct net_device *netdev,
struct ethtool_ts_info *info)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
ethtool_op_get_ts_info(netdev, info);
if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP))
return 0;
info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE);
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_ALL));
return 0;
}
static const struct ethtool_ops e1000_ethtool_ops = { static const struct ethtool_ops e1000_ethtool_ops = {
.get_settings = e1000_get_settings, .get_settings = e1000_get_settings,
.set_settings = e1000_set_settings, .set_settings = e1000_set_settings,
...@@ -2077,7 +2232,9 @@ static const struct ethtool_ops e1000_ethtool_ops = { ...@@ -2077,7 +2232,9 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_coalesce = e1000_get_coalesce, .get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce, .set_coalesce = e1000_set_coalesce,
.get_rxnfc = e1000_get_rxnfc, .get_rxnfc = e1000_get_rxnfc,
.get_ts_info = ethtool_op_get_ts_info, .get_ts_info = e1000e_get_ts_info,
.get_eee = e1000e_get_eee,
.set_eee = e1000e_set_eee,
}; };
void e1000e_set_ethtool_ops(struct net_device *netdev) void e1000e_set_ethtool_ops(struct net_device *netdev)
......
...@@ -60,8 +60,10 @@ enum e1e_registers { ...@@ -60,8 +60,10 @@ enum e1e_registers {
E1000_EIAC_82574 = 0x000DC, /* Ext. Interrupt Auto Clear - RW */ E1000_EIAC_82574 = 0x000DC, /* Ext. Interrupt Auto Clear - RW */
E1000_IAM = 0x000E0, /* Interrupt Acknowledge Auto Mask */ E1000_IAM = 0x000E0, /* Interrupt Acknowledge Auto Mask */
E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */ E1000_IVAR = 0x000E4, /* Interrupt Vector Allocation - RW */
E1000_FEXTNVM7 = 0x000E4, /* Future Extended NVM 7 - RW */
E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */ E1000_EITR_82574_BASE = 0x000E8, /* Interrupt Throttling - RW */
#define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2)) #define E1000_EITR_82574(_n) (E1000_EITR_82574_BASE + (_n << 2))
E1000_LPIC = 0x000FC, /* Low Power Idle Control - RW */
E1000_RCTL = 0x00100, /* Rx Control - RW */ E1000_RCTL = 0x00100, /* Rx Control - RW */
E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */ E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */
E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */ E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */
...@@ -240,6 +242,15 @@ enum e1e_registers { ...@@ -240,6 +242,15 @@ enum e1e_registers {
#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4)) #define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4))
#define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE #define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE
E1000_HICR = 0x08F00, /* Host Interface Control */ E1000_HICR = 0x08F00, /* Host Interface Control */
E1000_SYSTIML = 0x0B600, /* System time register Low - RO */
E1000_SYSTIMH = 0x0B604, /* System time register High - RO */
E1000_TIMINCA = 0x0B608, /* Increment attributes register - RW */
E1000_TSYNCTXCTL = 0x0B614, /* Tx Time Sync Control register - RW */
E1000_TXSTMPL = 0x0B618, /* Tx timestamp value Low - RO */
E1000_TXSTMPH = 0x0B61C, /* Tx timestamp value High - RO */
E1000_TSYNCRXCTL = 0x0B620, /* Rx Time Sync Control register - RW */
E1000_RXSTMPL = 0x0B624, /* Rx timestamp Low - RO */
E1000_RXSTMPH = 0x0B628, /* Rx timestamp High - RO */
}; };
#define E1000_MAX_PHY_ADDR 4 #define E1000_MAX_PHY_ADDR 4
......
...@@ -148,28 +148,6 @@ ...@@ -148,28 +148,6 @@
#define HV_PM_CTRL PHY_REG(770, 17) #define HV_PM_CTRL PHY_REG(770, 17)
#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
/* PHY Low Power Idle Control */
#define I82579_LPI_CTRL PHY_REG(772, 20)
#define I82579_LPI_CTRL_100_ENABLE 0x2000
#define I82579_LPI_CTRL_1000_ENABLE 0x4000
#define I82579_LPI_CTRL_ENABLE_MASK 0x6000
#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80
/* Extended Management Interface (EMI) Registers */
#define I82579_EMI_ADDR 0x10
#define I82579_EMI_DATA 0x11
#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */
#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */
#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */
#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */
#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */
#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */
#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
/* Intel Rapid Start Technology Support */ /* Intel Rapid Start Technology Support */
#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) #define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70)
#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 #define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
...@@ -829,7 +807,7 @@ static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address, ...@@ -829,7 +807,7 @@ static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address,
* *
* Assumes the SW/FW/HW Semaphore is already acquired. * Assumes the SW/FW/HW Semaphore is already acquired.
**/ **/
static s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data)
{ {
return __e1000_access_emi_reg_locked(hw, addr, data, true); return __e1000_access_emi_reg_locked(hw, addr, data, true);
} }
...@@ -4623,6 +4601,7 @@ const struct e1000_info e1000_pch2_info = { ...@@ -4623,6 +4601,7 @@ const struct e1000_info e1000_pch2_info = {
.mac = e1000_pch2lan, .mac = e1000_pch2lan,
.flags = FLAG_IS_ICH .flags = FLAG_IS_ICH
| FLAG_HAS_WOL | FLAG_HAS_WOL
| FLAG_HAS_HW_TIMESTAMP
| FLAG_HAS_CTRLEXT_ON_LOAD | FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT | FLAG_HAS_AMT
| FLAG_HAS_FLASH | FLAG_HAS_FLASH
...@@ -4642,6 +4621,7 @@ const struct e1000_info e1000_pch_lpt_info = { ...@@ -4642,6 +4621,7 @@ const struct e1000_info e1000_pch_lpt_info = {
.mac = e1000_pch_lpt, .mac = e1000_pch_lpt,
.flags = FLAG_IS_ICH .flags = FLAG_IS_ICH
| FLAG_HAS_WOL | FLAG_HAS_WOL
| FLAG_HAS_HW_TIMESTAMP
| FLAG_HAS_CTRLEXT_ON_LOAD | FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT | FLAG_HAS_AMT
| FLAG_HAS_FLASH | FLAG_HAS_FLASH
......
This diff is collapsed.
...@@ -34,4 +34,4 @@ obj-$(CONFIG_IGB) += igb.o ...@@ -34,4 +34,4 @@ obj-$(CONFIG_IGB) += igb.o
igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \ igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
e1000_i210.o igb_ptp.o e1000_i210.o igb_ptp.o igb_hwmon.o
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/i2c.h>
#include "e1000_mac.h" #include "e1000_mac.h"
#include "e1000_82575.h" #include "e1000_82575.h"
...@@ -2302,18 +2303,157 @@ s32 igb_set_eee_i350(struct e1000_hw *hw) ...@@ -2302,18 +2303,157 @@ s32 igb_set_eee_i350(struct e1000_hw *hw)
return ret_val; return ret_val;
} }
static const u8 e1000_emc_temp_data[4] = {
E1000_EMC_INTERNAL_DATA,
E1000_EMC_DIODE1_DATA,
E1000_EMC_DIODE2_DATA,
E1000_EMC_DIODE3_DATA
};
static const u8 e1000_emc_therm_limit[4] = {
E1000_EMC_INTERNAL_THERM_LIMIT,
E1000_EMC_DIODE1_THERM_LIMIT,
E1000_EMC_DIODE2_THERM_LIMIT,
E1000_EMC_DIODE3_THERM_LIMIT
};
/* igb_get_thermal_sensor_data_generic - Gathers thermal sensor data
* @hw: pointer to hardware structure
*
* Updates the temperatures in mac.thermal_sensor_data
*/
s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw)
{
s32 status = E1000_SUCCESS;
u16 ets_offset;
u16 ets_cfg;
u16 ets_sensor;
u8 num_sensors;
u8 sensor_index;
u8 sensor_location;
u8 i;
struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0))
return E1000_NOT_IMPLEMENTED;
data->sensor[0].temp = (rd32(E1000_THMJT) & 0xFF);
/* Return the internal sensor only if ETS is unsupported */
hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset);
if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF))
return status;
hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg);
if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT)
!= NVM_ETS_TYPE_EMC)
return E1000_NOT_IMPLEMENTED;
num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK);
if (num_sensors > E1000_MAX_SENSORS)
num_sensors = E1000_MAX_SENSORS;
for (i = 1; i < num_sensors; i++) {
hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor);
sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >>
NVM_ETS_DATA_INDEX_SHIFT);
sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >>
NVM_ETS_DATA_LOC_SHIFT);
if (sensor_location != 0)
hw->phy.ops.read_i2c_byte(hw,
e1000_emc_temp_data[sensor_index],
E1000_I2C_THERMAL_SENSOR_ADDR,
&data->sensor[i].temp);
}
return status;
}
/* igb_init_thermal_sensor_thresh_generic - Sets thermal sensor thresholds
* @hw: pointer to hardware structure
*
* Sets the thermal sensor thresholds according to the NVM map
* and save off the threshold and location values into mac.thermal_sensor_data
*/
s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw)
{
s32 status = E1000_SUCCESS;
u16 ets_offset;
u16 ets_cfg;
u16 ets_sensor;
u8 low_thresh_delta;
u8 num_sensors;
u8 sensor_index;
u8 sensor_location;
u8 therm_limit;
u8 i;
struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0))
return E1000_NOT_IMPLEMENTED;
memset(data, 0, sizeof(struct e1000_thermal_sensor_data));
data->sensor[0].location = 0x1;
data->sensor[0].caution_thresh =
(rd32(E1000_THHIGHTC) & 0xFF);
data->sensor[0].max_op_thresh =
(rd32(E1000_THLOWTC) & 0xFF);
/* Return the internal sensor only if ETS is unsupported */
hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset);
if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF))
return status;
hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg);
if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT)
!= NVM_ETS_TYPE_EMC)
return E1000_NOT_IMPLEMENTED;
low_thresh_delta = ((ets_cfg & NVM_ETS_LTHRES_DELTA_MASK) >>
NVM_ETS_LTHRES_DELTA_SHIFT);
num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK);
for (i = 1; i <= num_sensors; i++) {
hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor);
sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >>
NVM_ETS_DATA_INDEX_SHIFT);
sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >>
NVM_ETS_DATA_LOC_SHIFT);
therm_limit = ets_sensor & NVM_ETS_DATA_HTHRESH_MASK;
hw->phy.ops.write_i2c_byte(hw,
e1000_emc_therm_limit[sensor_index],
E1000_I2C_THERMAL_SENSOR_ADDR,
therm_limit);
if ((i < E1000_MAX_SENSORS) && (sensor_location != 0)) {
data->sensor[i].location = sensor_location;
data->sensor[i].caution_thresh = therm_limit;
data->sensor[i].max_op_thresh = therm_limit -
low_thresh_delta;
}
}
return status;
}
static struct e1000_mac_operations e1000_mac_ops_82575 = { static struct e1000_mac_operations e1000_mac_ops_82575 = {
.init_hw = igb_init_hw_82575, .init_hw = igb_init_hw_82575,
.check_for_link = igb_check_for_link_82575, .check_for_link = igb_check_for_link_82575,
.rar_set = igb_rar_set, .rar_set = igb_rar_set,
.read_mac_addr = igb_read_mac_addr_82575, .read_mac_addr = igb_read_mac_addr_82575,
.get_speed_and_duplex = igb_get_speed_and_duplex_copper, .get_speed_and_duplex = igb_get_speed_and_duplex_copper,
#ifdef CONFIG_IGB_HWMON
.get_thermal_sensor_data = igb_get_thermal_sensor_data_generic,
.init_thermal_sensor_thresh = igb_init_thermal_sensor_thresh_generic,
#endif
}; };
static struct e1000_phy_operations e1000_phy_ops_82575 = { static struct e1000_phy_operations e1000_phy_ops_82575 = {
.acquire = igb_acquire_phy_82575, .acquire = igb_acquire_phy_82575,
.get_cfg_done = igb_get_cfg_done_82575, .get_cfg_done = igb_get_cfg_done_82575,
.release = igb_release_phy_82575, .release = igb_release_phy_82575,
.write_i2c_byte = igb_write_i2c_byte,
.read_i2c_byte = igb_read_i2c_byte,
}; };
static struct e1000_nvm_operations e1000_nvm_ops_82575 = { static struct e1000_nvm_operations e1000_nvm_ops_82575 = {
......
...@@ -32,6 +32,10 @@ extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); ...@@ -32,6 +32,10 @@ extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw); extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw); extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
extern s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
extern s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
(ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 8) | \
...@@ -260,5 +264,16 @@ void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); ...@@ -260,5 +264,16 @@ void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
u16 igb_rxpbs_adjust_82580(u32 data); u16 igb_rxpbs_adjust_82580(u32 data);
s32 igb_set_eee_i350(struct e1000_hw *); s32 igb_set_eee_i350(struct e1000_hw *);
s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *);
s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw);
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
#define E1000_EMC_INTERNAL_DATA 0x00
#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20
#define E1000_EMC_DIODE1_DATA 0x01
#define E1000_EMC_DIODE1_THERM_LIMIT 0x19
#define E1000_EMC_DIODE2_DATA 0x23
#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A
#define E1000_EMC_DIODE3_DATA 0x2A
#define E1000_EMC_DIODE3_THERM_LIMIT 0x30
#endif #endif
...@@ -470,6 +470,7 @@ ...@@ -470,6 +470,7 @@
#define E1000_ERR_NO_SPACE 17 #define E1000_ERR_NO_SPACE 17
#define E1000_ERR_NVM_PBA_SECTION 18 #define E1000_ERR_NVM_PBA_SECTION 18
#define E1000_ERR_INVM_VALUE_NOT_FOUND 19 #define E1000_ERR_INVM_VALUE_NOT_FOUND 19
#define E1000_ERR_I2C 20
/* Loop limit on how long we wait for auto-negotiation to complete */ /* Loop limit on how long we wait for auto-negotiation to complete */
#define COPPER_LINK_UP_LIMIT 10 #define COPPER_LINK_UP_LIMIT 10
...@@ -674,6 +675,18 @@ ...@@ -674,6 +675,18 @@
#define NVM_COMB_VER_SHFT 8 #define NVM_COMB_VER_SHFT 8
#define NVM_VER_INVALID 0xFFFF #define NVM_VER_INVALID 0xFFFF
#define NVM_ETRACK_SHIFT 16 #define NVM_ETRACK_SHIFT 16
#define NVM_ETS_CFG 0x003E
#define NVM_ETS_LTHRES_DELTA_MASK 0x07C0
#define NVM_ETS_LTHRES_DELTA_SHIFT 6
#define NVM_ETS_TYPE_MASK 0x0038
#define NVM_ETS_TYPE_SHIFT 3
#define NVM_ETS_TYPE_EMC 0x000
#define NVM_ETS_NUM_SENSORS_MASK 0x0007
#define NVM_ETS_DATA_LOC_MASK 0x3C00
#define NVM_ETS_DATA_LOC_SHIFT 10
#define NVM_ETS_DATA_INDEX_MASK 0x0300
#define NVM_ETS_DATA_INDEX_SHIFT 8
#define NVM_ETS_DATA_HTHRESH_MASK 0x00FF
#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
......
...@@ -325,6 +325,10 @@ struct e1000_mac_operations { ...@@ -325,6 +325,10 @@ struct e1000_mac_operations {
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *); s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
s32 (*acquire_swfw_sync)(struct e1000_hw *, u16); s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
void (*release_swfw_sync)(struct e1000_hw *, u16); void (*release_swfw_sync)(struct e1000_hw *, u16);
#ifdef CONFIG_IGB_HWMON
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
#endif
}; };
...@@ -342,6 +346,8 @@ struct e1000_phy_operations { ...@@ -342,6 +346,8 @@ struct e1000_phy_operations {
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_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)(struct e1000_hw *, u32, u16);
s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
}; };
struct e1000_nvm_operations { struct e1000_nvm_operations {
...@@ -354,6 +360,19 @@ struct e1000_nvm_operations { ...@@ -354,6 +360,19 @@ struct e1000_nvm_operations {
s32 (*valid_led_default)(struct e1000_hw *, u16 *); s32 (*valid_led_default)(struct e1000_hw *, 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_info { struct e1000_info {
s32 (*get_invariants)(struct e1000_hw *); s32 (*get_invariants)(struct e1000_hw *);
struct e1000_mac_operations *mac_ops; struct e1000_mac_operations *mac_ops;
...@@ -399,6 +418,7 @@ struct e1000_mac_info { ...@@ -399,6 +418,7 @@ struct e1000_mac_info {
bool report_tx_early; bool report_tx_early;
bool serdes_has_link; bool serdes_has_link;
bool tx_pkt_filtering; bool tx_pkt_filtering;
struct e1000_thermal_sensor_data thermal_sensor_data;
}; };
struct e1000_phy_info { struct e1000_phy_info {
......
...@@ -75,6 +75,14 @@ ...@@ -75,6 +75,14 @@
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */
#define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */
#define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */
#define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */
#define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */
#define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */
#define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */
#define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */
/* IEEE 1588 TIMESYNCH */ /* IEEE 1588 TIMESYNCH */
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
...@@ -124,6 +132,14 @@ ...@@ -124,6 +132,14 @@
/* Split and Replication RX Control - RW */ /* Split and Replication RX Control - RW */
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
/* Thermal sensor configuration and status registers */
#define E1000_THMJT 0x08100 /* Junction Temperature */
#define E1000_THLOWTC 0x08104 /* Low Threshold Control */
#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */
#define E1000_THHIGHTC 0x0810C /* High Threshold Control */
#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
/* /*
* Convenience macros * Convenience macros
* *
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
struct igb_adapter; struct igb_adapter;
...@@ -219,6 +221,7 @@ struct igb_ring { ...@@ -219,6 +221,7 @@ struct igb_ring {
struct igb_tx_buffer *tx_buffer_info; struct igb_tx_buffer *tx_buffer_info;
struct igb_rx_buffer *rx_buffer_info; struct igb_rx_buffer *rx_buffer_info;
}; };
unsigned long last_rx_timestamp;
void *desc; /* descriptor ring memory */ void *desc; /* descriptor ring memory */
unsigned long flags; /* ring specific flags */ unsigned long flags; /* ring specific flags */
void __iomem *tail; /* pointer to ring tail register */ void __iomem *tail; /* pointer to ring tail register */
...@@ -301,6 +304,32 @@ static inline int igb_desc_unused(struct igb_ring *ring) ...@@ -301,6 +304,32 @@ static inline int igb_desc_unused(struct igb_ring *ring)
return ring->count + ring->next_to_clean - ring->next_to_use - 1; return ring->count + ring->next_to_clean - ring->next_to_use - 1;
} }
struct igb_i2c_client_list {
struct i2c_client *client;
struct igb_i2c_client_list *next;
};
#ifdef CONFIG_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
/* board specific private data structure */ /* board specific private data structure */
struct igb_adapter { struct igb_adapter {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
...@@ -386,11 +415,22 @@ struct igb_adapter { ...@@ -386,11 +415,22 @@ struct igb_adapter {
struct delayed_work ptp_overflow_work; struct delayed_work ptp_overflow_work;
struct work_struct ptp_tx_work; struct work_struct ptp_tx_work;
struct sk_buff *ptp_tx_skb; struct sk_buff *ptp_tx_skb;
unsigned long ptp_tx_start;
unsigned long last_rx_ptp_check;
spinlock_t tmreg_lock; spinlock_t tmreg_lock;
struct cyclecounter cc; struct cyclecounter cc;
struct timecounter tc; struct timecounter tc;
u32 tx_hwtstamp_timeouts;
u32 rx_hwtstamp_cleared;
char fw_version[32]; char fw_version[32];
#ifdef CONFIG_IGB_HWMON
struct hwmon_buff igb_hwmon_buff;
bool ets;
#endif
struct i2c_algo_bit_data i2c_algo;
struct i2c_adapter i2c_adap;
struct igb_i2c_client_list *i2c_clients;
}; };
#define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_HAS_MSI (1 << 0)
...@@ -449,6 +489,7 @@ extern void igb_ptp_init(struct igb_adapter *adapter); ...@@ -449,6 +489,7 @@ extern void igb_ptp_init(struct igb_adapter *adapter);
extern void igb_ptp_stop(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_reset(struct igb_adapter *adapter);
extern void igb_ptp_tx_work(struct work_struct *work); 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_tx_hwtstamp(struct igb_adapter *adapter);
extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
struct sk_buff *skb); struct sk_buff *skb);
...@@ -466,7 +507,10 @@ static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, ...@@ -466,7 +507,10 @@ static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd); struct ifreq *ifr, int cmd);
#ifdef CONFIG_IGB_HWMON
extern void igb_sysfs_exit(struct igb_adapter *adapter);
extern int igb_sysfs_init(struct igb_adapter *adapter);
#endif
static inline s32 igb_reset_phy(struct e1000_hw *hw) static inline s32 igb_reset_phy(struct e1000_hw *hw)
{ {
if (hw->phy.ops.reset) if (hw->phy.ops.reset)
......
...@@ -92,6 +92,8 @@ static const struct igb_stats igb_gstrings_stats[] = { ...@@ -92,6 +92,8 @@ static const struct igb_stats igb_gstrings_stats[] = {
IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc), IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
IGB_STAT("os2bmc_tx_by_host", stats.o2bspc), IGB_STAT("os2bmc_tx_by_host", stats.o2bspc),
IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc), IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc),
IGB_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
IGB_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
}; };
#define IGB_NETDEV_STAT(_net_stat) { \ #define IGB_NETDEV_STAT(_net_stat) { \
...@@ -2272,12 +2274,21 @@ static int igb_get_ts_info(struct net_device *dev, ...@@ -2272,12 +2274,21 @@ static int igb_get_ts_info(struct net_device *dev,
struct igb_adapter *adapter = netdev_priv(dev); struct igb_adapter *adapter = netdev_priv(dev);
switch (adapter->hw.mac.type) { switch (adapter->hw.mac.type) {
case e1000_82575:
info->so_timestamping =
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE;
return 0;
case e1000_82576: case e1000_82576:
case e1000_82580: case e1000_82580:
case e1000_i350: case e1000_i350:
case e1000_i210: case e1000_i210:
case e1000_i211: case e1000_i211:
info->so_timestamping = info->so_timestamping =
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE; SOF_TIMESTAMPING_RAW_HARDWARE;
......
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
Copyright(c) 2007-2012 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "igb.h"
#include "e1000_82575.h"
#include "e1000_hw.h"
#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>
#ifdef CONFIG_IGB_HWMON
/* 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
This diff is collapsed.
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/ptp_classify.h>
#include "igb.h" #include "igb.h"
...@@ -70,6 +71,7 @@ ...@@ -70,6 +71,7 @@
*/ */
#define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9) #define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9)
#define IGB_PTP_TX_TIMEOUT (HZ * 15)
#define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT) #define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT)
#define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1) #define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1)
#define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT) #define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT)
...@@ -396,6 +398,15 @@ void igb_ptp_tx_work(struct work_struct *work) ...@@ -396,6 +398,15 @@ void igb_ptp_tx_work(struct work_struct *work)
if (!adapter->ptp_tx_skb) if (!adapter->ptp_tx_skb)
return; 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 = rd32(E1000_TSYNCTXCTL); tsynctxctl = rd32(E1000_TSYNCTXCTL);
if (tsynctxctl & E1000_TSYNCTXCTL_VALID) if (tsynctxctl & E1000_TSYNCTXCTL_VALID)
igb_ptp_tx_hwtstamp(adapter); igb_ptp_tx_hwtstamp(adapter);
...@@ -418,6 +429,51 @@ static void igb_ptp_overflow_check(struct work_struct *work) ...@@ -418,6 +429,51 @@ static void igb_ptp_overflow_check(struct work_struct *work)
IGB_SYSTIM_OVERFLOW_PERIOD); 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 = rd32(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)) {
rd32(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 * igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp
* @adapter: Board private structure. * @adapter: Board private structure.
...@@ -643,7 +699,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, ...@@ -643,7 +699,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
else else
wr32(E1000_ETQF(3), 0); wr32(E1000_ETQF(3), 0);
#define PTP_PORT 319
/* L4 Queue Filter[3]: filter by destination port and protocol */ /* L4 Queue Filter[3]: filter by destination port and protocol */
if (is_l4) { if (is_l4) {
u32 ftqf = (IPPROTO_UDP /* UDP */ u32 ftqf = (IPPROTO_UDP /* UDP */
...@@ -652,12 +707,12 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, ...@@ -652,12 +707,12 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
| E1000_FTQF_MASK); /* mask all inputs */ | E1000_FTQF_MASK); /* mask all inputs */
ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */ ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */
wr32(E1000_IMIR(3), htons(PTP_PORT)); wr32(E1000_IMIR(3), htons(PTP_EV_PORT));
wr32(E1000_IMIREXT(3), wr32(E1000_IMIREXT(3),
(E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP));
if (hw->mac.type == e1000_82576) { if (hw->mac.type == e1000_82576) {
/* enable source port check */ /* enable source port check */
wr32(E1000_SPQF(3), htons(PTP_PORT)); wr32(E1000_SPQF(3), htons(PTP_EV_PORT));
ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
} }
wr32(E1000_FTQF(3), ftqf); wr32(E1000_FTQF(3), ftqf);
...@@ -801,6 +856,10 @@ void igb_ptp_stop(struct igb_adapter *adapter) ...@@ -801,6 +856,10 @@ void igb_ptp_stop(struct igb_adapter *adapter)
} }
cancel_work_sync(&adapter->ptp_tx_work); 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) { if (adapter->ptp_clock) {
ptp_clock_unregister(adapter->ptp_clock); ptp_clock_unregister(adapter->ptp_clock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment