Commit 2dabf0c4 authored by David S. Miller's avatar David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
100GbE Intel Wired LAN Driver Updates 2016-04-20

This series contains updates to fm10k only.

Jacob provides majority of the changes in this series, starting with the
addition of helper functions to reduce code duplication and the amount
of code indentation.  Fixed the use or should we say abuse of the ethtool
stats API, which could result in corrupt memory or misleading statistic
output.  Added the appropriate rtnl_lock() and rtnl_unlock() to avoid
RCU warnings during AER events.  Come to find out, the PTP/1588 support
is not working with the current version of switch management software
and possibly never worked, so just remove support for PTP/1588 for now.
Fixed how error responses from the switch manager after a LPORT_MAP
request are handled, originally which were silently being ignored.
Fixed up code documentation to hopefully ease the code and comment
comprehension.  Fixed a possible NULL pointer dereference after a
kcalloc(), where when writing a new default redirection table, and we
needed to populate a new RSS table using ethtool_rxfh_indir_default().
We populate this table into a region of memory allocated using kcalloc()
but never check it for NULL.

Alex adds support for bulk transmit cleanup for fm10k, like he did for
all of our other drivers.

Ngai-Mint fixes a number of issues with the unicast and multicast address
syncs.  Where an issue would occur when the netdev is pre-configured to
either multicast mode and is enabled for the first time.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 10c9ead9 dc1b4c2b
################################################################################ ################################################################################
# #
# Intel Ethernet Switch Host Interface Driver # Intel(R) Ethernet Switch Host Interface Driver
# Copyright(c) 2013 - 2015 Intel Corporation. # Copyright(c) 2013 - 2016 Intel Corporation.
# #
# This program is free software; you can redistribute it and/or modify it # This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License, # under the terms and conditions of the GNU General Public License,
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
################################################################################ ################################################################################
# #
# Makefile for the Intel(R) FM10000 Ethernet Switch Host Interface driver # Makefile for the Intel(R) Ethernet Switch Host Interface Driver
# #
obj-$(CONFIG_FM10K) += fm10k.o obj-$(CONFIG_FM10K) += fm10k.o
...@@ -30,7 +30,6 @@ obj-$(CONFIG_FM10K) += fm10k.o ...@@ -30,7 +30,6 @@ obj-$(CONFIG_FM10K) += fm10k.o
fm10k-y := fm10k_main.o \ fm10k-y := fm10k_main.o \
fm10k_common.o \ fm10k_common.o \
fm10k_pci.o \ fm10k_pci.o \
fm10k_ptp.o \
fm10k_netdev.o \ fm10k_netdev.o \
fm10k_ethtool.o \ fm10k_ethtool.o \
fm10k_pf.o \ fm10k_pf.o \
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -27,9 +27,6 @@ ...@@ -27,9 +27,6 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/net_tstamp.h>
#include <linux/clocksource.h>
#include <linux/ptp_clock_kernel.h>
#include "fm10k_pf.h" #include "fm10k_pf.h"
#include "fm10k_vf.h" #include "fm10k_vf.h"
...@@ -333,6 +330,7 @@ struct fm10k_intfc { ...@@ -333,6 +330,7 @@ struct fm10k_intfc {
unsigned long last_reset; unsigned long last_reset;
unsigned long link_down_event; unsigned long link_down_event;
bool host_ready; bool host_ready;
bool lport_map_failed;
u32 reta[FM10K_RETA_SIZE]; u32 reta[FM10K_RETA_SIZE];
u32 rssrk[FM10K_RSSRK_SIZE]; u32 rssrk[FM10K_RSSRK_SIZE];
...@@ -342,22 +340,8 @@ struct fm10k_intfc { ...@@ -342,22 +340,8 @@ struct fm10k_intfc {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *dbg_intfc; struct dentry *dbg_intfc;
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
struct ptp_clock_info ptp_caps;
struct ptp_clock *ptp_clock;
struct sk_buff_head ts_tx_skb_queue;
u32 tx_hwtstamp_timeouts;
struct hwtstamp_config ts_config;
/* We are unable to actually adjust the clock beyond the frequency
* value. Once the clock is started there is no resetting it. As
* such we maintain a separate offset from the actual hardware clock
* to allow for offset adjustment.
*/
s64 ptp_adjust;
rwlock_t systime_lock;
#ifdef CONFIG_DCB #ifdef CONFIG_DCB
u8 pfc_en; u8 pfc_en;
#endif #endif
...@@ -546,21 +530,6 @@ static inline void fm10k_dbg_init(void) {} ...@@ -546,21 +530,6 @@ static inline void fm10k_dbg_init(void) {}
static inline void fm10k_dbg_exit(void) {} static inline void fm10k_dbg_exit(void) {}
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
/* Time Stamping */
void fm10k_systime_to_hwtstamp(struct fm10k_intfc *interface,
struct skb_shared_hwtstamps *hwtstamp,
u64 systime);
void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb);
void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort,
u64 systime);
void fm10k_ts_reset(struct fm10k_intfc *interface);
void fm10k_ts_init(struct fm10k_intfc *interface);
void fm10k_ts_tx_subtask(struct fm10k_intfc *interface);
void fm10k_ptp_register(struct fm10k_intfc *interface);
void fm10k_ptp_unregister(struct fm10k_intfc *interface);
int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
/* DCB */ /* DCB */
#ifdef CONFIG_DCB #ifdef CONFIG_DCB
void fm10k_dcbnl_set_ops(struct net_device *dev); void fm10k_dcbnl_set_ops(struct net_device *dev);
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -77,19 +77,6 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = { ...@@ -77,19 +77,6 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = {
FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail), FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail),
FM10K_STAT("tx_hang_count", tx_timeout_count), FM10K_STAT("tx_hang_count", tx_timeout_count),
FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
};
static const struct fm10k_stats fm10k_gstrings_debug_stats[] = {
FM10K_STAT("hw_sm_mbx_full", hw_sm_mbx_full),
FM10K_STAT("hw_csum_tx_good", hw_csum_tx_good),
FM10K_STAT("hw_csum_rx_good", hw_csum_rx_good),
FM10K_STAT("rx_switch_errors", rx_switch_errors),
FM10K_STAT("rx_drops", rx_drops),
FM10K_STAT("rx_pp_errors", rx_pp_errors),
FM10K_STAT("rx_link_errors", rx_link_errors),
FM10K_STAT("rx_length_errors", rx_length_errors),
}; };
static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {
...@@ -121,13 +108,21 @@ static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = { ...@@ -121,13 +108,21 @@ static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = {
FM10K_MBX_STAT("mbx_rx_mbmem_pushed", rx_mbmem_pushed), FM10K_MBX_STAT("mbx_rx_mbmem_pushed", rx_mbmem_pushed),
}; };
#define FM10K_QUEUE_STAT(_name, _stat) { \
.stat_string = _name, \
.sizeof_stat = FIELD_SIZEOF(struct fm10k_ring, _stat), \
.stat_offset = offsetof(struct fm10k_ring, _stat) \
}
static const struct fm10k_stats fm10k_gstrings_queue_stats[] = {
FM10K_QUEUE_STAT("packets", stats.packets),
FM10K_QUEUE_STAT("bytes", stats.bytes),
};
#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats) #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats)
#define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats)
#define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats) #define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats)
#define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats) #define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats)
#define FM10K_QUEUE_STATS_LEN ARRAY_SIZE(fm10k_gstrings_queue_stats)
#define FM10K_QUEUE_STATS_LEN(_n) \
((_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64)))
#define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \ #define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \
FM10K_NETDEV_STATS_LEN + \ FM10K_NETDEV_STATS_LEN + \
...@@ -145,12 +140,10 @@ enum fm10k_self_test_types { ...@@ -145,12 +140,10 @@ enum fm10k_self_test_types {
}; };
enum { enum {
FM10K_PRV_FLAG_DEBUG_STATS,
FM10K_PRV_FLAG_LEN, FM10K_PRV_FLAG_LEN,
}; };
static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = { static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = {
"debug-statistics",
}; };
static void fm10k_add_stat_strings(char **p, const char *prefix, static void fm10k_add_stat_strings(char **p, const char *prefix,
...@@ -169,7 +162,6 @@ static void fm10k_add_stat_strings(char **p, const char *prefix, ...@@ -169,7 +162,6 @@ static void fm10k_add_stat_strings(char **p, const char *prefix,
static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) static void fm10k_get_stat_strings(struct net_device *dev, u8 *data)
{ {
struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_intfc *interface = netdev_priv(dev);
struct fm10k_iov_data *iov_data = interface->iov_data;
char *p = (char *)data; char *p = (char *)data;
unsigned int i; unsigned int i;
...@@ -179,10 +171,6 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) ...@@ -179,10 +171,6 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data)
fm10k_add_stat_strings(&p, "", fm10k_gstrings_global_stats, fm10k_add_stat_strings(&p, "", fm10k_gstrings_global_stats,
FM10K_GLOBAL_STATS_LEN); FM10K_GLOBAL_STATS_LEN);
if (interface->flags & FM10K_FLAG_DEBUG_STATS)
fm10k_add_stat_strings(&p, "", fm10k_gstrings_debug_stats,
FM10K_DEBUG_STATS_LEN);
fm10k_add_stat_strings(&p, "", fm10k_gstrings_mbx_stats, fm10k_add_stat_strings(&p, "", fm10k_gstrings_mbx_stats,
FM10K_MBX_STATS_LEN); FM10K_MBX_STATS_LEN);
...@@ -190,26 +178,18 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) ...@@ -190,26 +178,18 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data)
fm10k_add_stat_strings(&p, "", fm10k_gstrings_pf_stats, fm10k_add_stat_strings(&p, "", fm10k_gstrings_pf_stats,
FM10K_PF_STATS_LEN); FM10K_PF_STATS_LEN);
if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { for (i = 0; i < interface->hw.mac.max_queues; i++) {
for (i = 0; i < iov_data->num_vfs; i++) {
char prefix[ETH_GSTRING_LEN]; char prefix[ETH_GSTRING_LEN];
snprintf(prefix, ETH_GSTRING_LEN, "vf_%u_", i); snprintf(prefix, ETH_GSTRING_LEN, "tx_queue_%u_", i);
fm10k_add_stat_strings(&p, prefix, fm10k_add_stat_strings(&p, prefix,
fm10k_gstrings_mbx_stats, fm10k_gstrings_queue_stats,
FM10K_MBX_STATS_LEN); FM10K_QUEUE_STATS_LEN);
}
}
for (i = 0; i < interface->hw.mac.max_queues; i++) { snprintf(prefix, ETH_GSTRING_LEN, "rx_queue_%u_", i);
snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i); fm10k_add_stat_strings(&p, prefix,
p += ETH_GSTRING_LEN; fm10k_gstrings_queue_stats,
snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i); FM10K_QUEUE_STATS_LEN);
p += ETH_GSTRING_LEN;
snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i);
p += ETH_GSTRING_LEN;
snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i);
p += ETH_GSTRING_LEN;
} }
} }
...@@ -236,7 +216,6 @@ static void fm10k_get_strings(struct net_device *dev, ...@@ -236,7 +216,6 @@ static void fm10k_get_strings(struct net_device *dev,
static int fm10k_get_sset_count(struct net_device *dev, int sset) static int fm10k_get_sset_count(struct net_device *dev, int sset)
{ {
struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_intfc *interface = netdev_priv(dev);
struct fm10k_iov_data *iov_data = interface->iov_data;
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
int stats_len = FM10K_STATIC_STATS_LEN; int stats_len = FM10K_STATIC_STATS_LEN;
...@@ -244,19 +223,11 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset) ...@@ -244,19 +223,11 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset)
case ETH_SS_TEST: case ETH_SS_TEST:
return FM10K_TEST_LEN; return FM10K_TEST_LEN;
case ETH_SS_STATS: case ETH_SS_STATS:
stats_len += FM10K_QUEUE_STATS_LEN(hw->mac.max_queues); stats_len += hw->mac.max_queues * 2 * FM10K_QUEUE_STATS_LEN;
if (hw->mac.type != fm10k_mac_vf) if (hw->mac.type != fm10k_mac_vf)
stats_len += FM10K_PF_STATS_LEN; stats_len += FM10K_PF_STATS_LEN;
if (interface->flags & FM10K_FLAG_DEBUG_STATS) {
stats_len += FM10K_DEBUG_STATS_LEN;
if (iov_data)
stats_len += FM10K_MBX_STATS_LEN *
iov_data->num_vfs;
}
return stats_len; return stats_len;
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
return FM10K_PRV_FLAG_LEN; return FM10K_PRV_FLAG_LEN;
...@@ -272,9 +243,10 @@ static void fm10k_add_ethtool_stats(u64 **data, void *pointer, ...@@ -272,9 +243,10 @@ static void fm10k_add_ethtool_stats(u64 **data, void *pointer,
unsigned int i; unsigned int i;
char *p; char *p;
/* simply skip forward if we were not given a valid pointer */
if (!pointer) { if (!pointer) {
*data += size; /* memory is not zero allocated so we have to clear it */
for (i = 0; i < size; i++)
*((*data)++) = 0;
return; return;
} }
...@@ -304,11 +276,9 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, ...@@ -304,11 +276,9 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats __always_unused *stats, struct ethtool_stats __always_unused *stats,
u64 *data) u64 *data)
{ {
const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64);
struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_intfc *interface = netdev_priv(netdev);
struct fm10k_iov_data *iov_data = interface->iov_data;
struct net_device_stats *net_stats = &netdev->stats; struct net_device_stats *net_stats = &netdev->stats;
int i, j; int i;
fm10k_update_stats(interface); fm10k_update_stats(interface);
...@@ -318,11 +288,6 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, ...@@ -318,11 +288,6 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
fm10k_add_ethtool_stats(&data, interface, fm10k_gstrings_global_stats, fm10k_add_ethtool_stats(&data, interface, fm10k_gstrings_global_stats,
FM10K_GLOBAL_STATS_LEN); FM10K_GLOBAL_STATS_LEN);
if (interface->flags & FM10K_FLAG_DEBUG_STATS)
fm10k_add_ethtool_stats(&data, interface,
fm10k_gstrings_debug_stats,
FM10K_DEBUG_STATS_LEN);
fm10k_add_ethtool_stats(&data, &interface->hw.mbx, fm10k_add_ethtool_stats(&data, &interface->hw.mbx,
fm10k_gstrings_mbx_stats, fm10k_gstrings_mbx_stats,
FM10K_MBX_STATS_LEN); FM10K_MBX_STATS_LEN);
...@@ -333,33 +298,18 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, ...@@ -333,33 +298,18 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
FM10K_PF_STATS_LEN); FM10K_PF_STATS_LEN);
} }
if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) {
for (i = 0; i < iov_data->num_vfs; i++) {
struct fm10k_vf_info *vf_info;
vf_info = &iov_data->vf_info[i];
fm10k_add_ethtool_stats(&data, &vf_info->mbx,
fm10k_gstrings_mbx_stats,
FM10K_MBX_STATS_LEN);
}
}
for (i = 0; i < interface->hw.mac.max_queues; i++) { for (i = 0; i < interface->hw.mac.max_queues; i++) {
struct fm10k_ring *ring; struct fm10k_ring *ring;
u64 *queue_stat;
ring = interface->tx_ring[i]; ring = interface->tx_ring[i];
if (ring) fm10k_add_ethtool_stats(&data, ring,
queue_stat = (u64 *)&ring->stats; fm10k_gstrings_queue_stats,
for (j = 0; j < stat_count; j++) FM10K_QUEUE_STATS_LEN);
*(data++) = ring ? queue_stat[j] : 0;
ring = interface->rx_ring[i]; ring = interface->rx_ring[i];
if (ring) fm10k_add_ethtool_stats(&data, ring,
queue_stat = (u64 *)&ring->stats; fm10k_gstrings_queue_stats,
for (j = 0; j < stat_count; j++) FM10K_QUEUE_STATS_LEN);
*(data++) = ring ? queue_stat[j] : 0;
} }
} }
...@@ -1003,27 +953,14 @@ static void fm10k_self_test(struct net_device *dev, ...@@ -1003,27 +953,14 @@ static void fm10k_self_test(struct net_device *dev,
static u32 fm10k_get_priv_flags(struct net_device *netdev) static u32 fm10k_get_priv_flags(struct net_device *netdev)
{ {
struct fm10k_intfc *interface = netdev_priv(netdev); return 0;
u32 priv_flags = 0;
if (interface->flags & FM10K_FLAG_DEBUG_STATS)
priv_flags |= BIT(FM10K_PRV_FLAG_DEBUG_STATS);
return priv_flags;
} }
static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags) static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags)
{ {
struct fm10k_intfc *interface = netdev_priv(netdev);
if (priv_flags >= BIT(FM10K_PRV_FLAG_LEN)) if (priv_flags >= BIT(FM10K_PRV_FLAG_LEN))
return -EINVAL; return -EINVAL;
if (priv_flags & BIT(FM10K_PRV_FLAG_DEBUG_STATS))
interface->flags |= FM10K_FLAG_DEBUG_STATS;
else
interface->flags &= ~FM10K_FLAG_DEBUG_STATS;
return 0; return 0;
} }
...@@ -1034,15 +971,29 @@ u32 fm10k_get_reta_size(struct net_device __always_unused *netdev) ...@@ -1034,15 +971,29 @@ u32 fm10k_get_reta_size(struct net_device __always_unused *netdev)
void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir) void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir)
{ {
u16 rss_i = interface->ring_feature[RING_F_RSS].indices;
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
int i; u32 table[4];
int i, j;
/* record entries to reta table */ /* record entries to reta table */
for (i = 0; i < FM10K_RETA_SIZE; i++, indir += 4) { for (i = 0; i < FM10K_RETA_SIZE; i++) {
u32 reta = indir[0] | u32 reta, n;
(indir[1] << 8) |
(indir[2] << 16) | /* generate a new table if we weren't given one */
(indir[3] << 24); for (j = 0; j < 4; j++) {
if (indir)
n = indir[i + j];
else
n = ethtool_rxfh_indir_default(i + j, rss_i);
table[j] = n;
}
reta = table[0] |
(table[1] << 8) |
(table[2] << 16) |
(table[3] << 24);
if (interface->reta[i] == reta) if (interface->reta[i] == reta)
continue; continue;
...@@ -1201,31 +1152,6 @@ static int fm10k_set_channels(struct net_device *dev, ...@@ -1201,31 +1152,6 @@ static int fm10k_set_channels(struct net_device *dev,
return fm10k_setup_tc(dev, netdev_get_num_tc(dev)); return fm10k_setup_tc(dev, netdev_get_num_tc(dev));
} }
static int fm10k_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
{
struct fm10k_intfc *interface = netdev_priv(dev);
info->so_timestamping =
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
if (interface->ptp_clock)
info->phc_index = ptp_clock_index(interface->ptp_clock);
else
info->phc_index = -1;
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
return 0;
}
static const struct ethtool_ops fm10k_ethtool_ops = { static const struct ethtool_ops fm10k_ethtool_ops = {
.get_strings = fm10k_get_strings, .get_strings = fm10k_get_strings,
.get_sset_count = fm10k_get_sset_count, .get_sset_count = fm10k_get_sset_count,
...@@ -1253,7 +1179,6 @@ static const struct ethtool_ops fm10k_ethtool_ops = { ...@@ -1253,7 +1179,6 @@ static const struct ethtool_ops fm10k_ethtool_ops = {
.set_rxfh = fm10k_set_rssh, .set_rxfh = fm10k_set_rssh,
.get_channels = fm10k_get_channels, .get_channels = fm10k_get_channels,
.set_channels = fm10k_set_channels, .set_channels = fm10k_set_channels,
.get_ts_info = fm10k_get_ts_info,
}; };
void fm10k_set_ethtool_ops(struct net_device *dev) void fm10k_set_ethtool_ops(struct net_device *dev)
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -29,15 +29,15 @@ ...@@ -29,15 +29,15 @@
#include "fm10k.h" #include "fm10k.h"
#define DRV_VERSION "0.19.3-k" #define DRV_VERSION "0.19.3-k"
#define DRV_SUMMARY "Intel(R) Ethernet Switch Host Interface Driver"
const char fm10k_driver_version[] = DRV_VERSION; const char fm10k_driver_version[] = DRV_VERSION;
char fm10k_driver_name[] = "fm10k"; char fm10k_driver_name[] = "fm10k";
static const char fm10k_driver_string[] = static const char fm10k_driver_string[] = DRV_SUMMARY;
"Intel(R) Ethernet Switch Host Interface Driver";
static const char fm10k_copyright[] = static const char fm10k_copyright[] =
"Copyright (c) 2013 Intel Corporation."; "Copyright (c) 2013 - 2016 Intel Corporation.";
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) Ethernet Switch Host Interface Driver"); MODULE_DESCRIPTION(DRV_SUMMARY);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
...@@ -424,19 +424,6 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring, ...@@ -424,19 +424,6 @@ static inline void fm10k_rx_hash(struct fm10k_ring *ring,
PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
} }
static void fm10k_rx_hwtstamp(struct fm10k_ring *rx_ring,
union fm10k_rx_desc *rx_desc,
struct sk_buff *skb)
{
struct fm10k_intfc *interface = rx_ring->q_vector->interface;
FM10K_CB(skb)->tstamp = rx_desc->q.timestamp;
if (unlikely(interface->flags & FM10K_FLAG_RX_TS_ENABLED))
fm10k_systime_to_hwtstamp(interface, skb_hwtstamps(skb),
le64_to_cpu(rx_desc->q.timestamp));
}
static void fm10k_type_trans(struct fm10k_ring *rx_ring, static void fm10k_type_trans(struct fm10k_ring *rx_ring,
union fm10k_rx_desc __maybe_unused *rx_desc, union fm10k_rx_desc __maybe_unused *rx_desc,
struct sk_buff *skb) struct sk_buff *skb)
...@@ -486,8 +473,6 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring, ...@@ -486,8 +473,6 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring,
fm10k_rx_checksum(rx_ring, rx_desc, skb); fm10k_rx_checksum(rx_ring, rx_desc, skb);
fm10k_rx_hwtstamp(rx_ring, rx_desc, skb);
FM10K_CB(skb)->fi.w.vlan = rx_desc->w.vlan; FM10K_CB(skb)->fi.w.vlan = rx_desc->w.vlan;
skb_record_rx_queue(skb, rx_ring->queue_index); skb_record_rx_queue(skb, rx_ring->queue_index);
...@@ -835,6 +820,8 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, ...@@ -835,6 +820,8 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
struct ipv6hdr *ipv6; struct ipv6hdr *ipv6;
u8 *raw; u8 *raw;
} network_hdr; } network_hdr;
u8 *transport_hdr;
__be16 frag_off;
__be16 protocol; __be16 protocol;
u8 l4_hdr = 0; u8 l4_hdr = 0;
...@@ -852,9 +839,11 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, ...@@ -852,9 +839,11 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
goto no_csum; goto no_csum;
} }
network_hdr.raw = skb_inner_network_header(skb); network_hdr.raw = skb_inner_network_header(skb);
transport_hdr = skb_inner_transport_header(skb);
} else { } else {
protocol = vlan_get_protocol(skb); protocol = vlan_get_protocol(skb);
network_hdr.raw = skb_network_header(skb); network_hdr.raw = skb_network_header(skb);
transport_hdr = skb_transport_header(skb);
} }
switch (protocol) { switch (protocol) {
...@@ -863,15 +852,17 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, ...@@ -863,15 +852,17 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
l4_hdr = network_hdr.ipv6->nexthdr; l4_hdr = network_hdr.ipv6->nexthdr;
if (likely((transport_hdr - network_hdr.raw) ==
sizeof(struct ipv6hdr)))
break;
ipv6_skip_exthdr(skb, network_hdr.raw - skb->data +
sizeof(struct ipv6hdr),
&l4_hdr, &frag_off);
if (unlikely(frag_off))
l4_hdr = NEXTHDR_FRAGMENT;
break; break;
default: default:
if (unlikely(net_ratelimit())) { break;
dev_warn(tx_ring->dev,
"partial checksum but ip version=%x!\n",
protocol);
}
tx_ring->tx_stats.csum_err++;
goto no_csum;
} }
switch (l4_hdr) { switch (l4_hdr) {
...@@ -884,9 +875,10 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, ...@@ -884,9 +875,10 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring,
default: default:
if (unlikely(net_ratelimit())) { if (unlikely(net_ratelimit())) {
dev_warn(tx_ring->dev, dev_warn(tx_ring->dev,
"partial checksum but l4 proto=%x!\n", "partial checksum, version=%d l4 proto=%x\n",
l4_hdr); protocol, l4_hdr);
} }
skb_checksum_help(skb);
tx_ring->tx_stats.csum_err++; tx_ring->tx_stats.csum_err++;
goto no_csum; goto no_csum;
} }
...@@ -912,11 +904,6 @@ static u8 fm10k_tx_desc_flags(struct sk_buff *skb, u32 tx_flags) ...@@ -912,11 +904,6 @@ static u8 fm10k_tx_desc_flags(struct sk_buff *skb, u32 tx_flags)
/* set type for advanced descriptor with frame checksum insertion */ /* set type for advanced descriptor with frame checksum insertion */
u32 desc_flags = 0; u32 desc_flags = 0;
/* set timestamping bits */
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
likely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
desc_flags |= FM10K_TXD_FLAG_TIME;
/* set checksum offload bits */ /* set checksum offload bits */
desc_flags |= FM10K_SET_FLAG(tx_flags, FM10K_TX_FLAGS_CSUM, desc_flags |= FM10K_SET_FLAG(tx_flags, FM10K_TX_FLAGS_CSUM,
FM10K_TXD_FLAG_CSUM); FM10K_TXD_FLAG_CSUM);
...@@ -1198,9 +1185,10 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface) ...@@ -1198,9 +1185,10 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface)
* fm10k_clean_tx_irq - Reclaim resources after transmit completes * fm10k_clean_tx_irq - Reclaim resources after transmit completes
* @q_vector: structure containing interrupt and ring information * @q_vector: structure containing interrupt and ring information
* @tx_ring: tx ring to clean * @tx_ring: tx ring to clean
* @napi_budget: Used to determine if we are in netpoll
**/ **/
static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
struct fm10k_ring *tx_ring) struct fm10k_ring *tx_ring, int napi_budget)
{ {
struct fm10k_intfc *interface = q_vector->interface; struct fm10k_intfc *interface = q_vector->interface;
struct fm10k_tx_buffer *tx_buffer; struct fm10k_tx_buffer *tx_buffer;
...@@ -1238,7 +1226,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, ...@@ -1238,7 +1226,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
total_packets += tx_buffer->gso_segs; total_packets += tx_buffer->gso_segs;
/* free the skb */ /* free the skb */
dev_consume_skb_any(tx_buffer->skb); napi_consume_skb(tx_buffer->skb, napi_budget);
/* unmap skb header data */ /* unmap skb header data */
dma_unmap_single(tx_ring->dev, dma_unmap_single(tx_ring->dev,
...@@ -1449,8 +1437,10 @@ static int fm10k_poll(struct napi_struct *napi, int budget) ...@@ -1449,8 +1437,10 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
int per_ring_budget, work_done = 0; int per_ring_budget, work_done = 0;
bool clean_complete = true; bool clean_complete = true;
fm10k_for_each_ring(ring, q_vector->tx) fm10k_for_each_ring(ring, q_vector->tx) {
clean_complete &= fm10k_clean_tx_irq(q_vector, ring); if (!fm10k_clean_tx_irq(q_vector, ring, budget))
clean_complete = false;
}
/* Handle case where we are called by netpoll with a budget of 0 */ /* Handle case where we are called by netpoll with a budget of 0 */
if (budget <= 0) if (budget <= 0)
...@@ -1468,7 +1458,8 @@ static int fm10k_poll(struct napi_struct *napi, int budget) ...@@ -1468,7 +1458,8 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget); int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget);
work_done += work; work_done += work;
clean_complete &= !!(work < per_ring_budget); if (work >= per_ring_budget)
clean_complete = false;
} }
/* If all work not completed, return budget and keep polling */ /* If all work not completed, return budget and keep polling */
...@@ -1943,8 +1934,7 @@ static void fm10k_assign_rings(struct fm10k_intfc *interface) ...@@ -1943,8 +1934,7 @@ static void fm10k_assign_rings(struct fm10k_intfc *interface)
static void fm10k_init_reta(struct fm10k_intfc *interface) static void fm10k_init_reta(struct fm10k_intfc *interface)
{ {
u16 i, rss_i = interface->ring_feature[RING_F_RSS].indices; u16 i, rss_i = interface->ring_feature[RING_F_RSS].indices;
struct net_device *netdev = interface->netdev; u32 reta;
u32 reta, *indir;
/* If the Rx flow indirection table has been configured manually, we /* If the Rx flow indirection table has been configured manually, we
* need to maintain it when possible. * need to maintain it when possible.
...@@ -1969,16 +1959,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) ...@@ -1969,16 +1959,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface)
} }
repopulate_reta: repopulate_reta:
indir = kcalloc(fm10k_get_reta_size(netdev), fm10k_write_reta(interface, NULL);
sizeof(indir[0]), GFP_KERNEL);
/* generate redirection table using the default kernel policy */
for (i = 0; i < fm10k_get_reta_size(netdev); i++)
indir[i] = ethtool_rxfh_indir_default(i, rss_i);
fm10k_write_reta(interface, indir);
kfree(indir);
} }
/** /**
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -243,9 +243,6 @@ void fm10k_clean_all_tx_rings(struct fm10k_intfc *interface) ...@@ -243,9 +243,6 @@ void fm10k_clean_all_tx_rings(struct fm10k_intfc *interface)
for (i = 0; i < interface->num_tx_queues; i++) for (i = 0; i < interface->num_tx_queues; i++)
fm10k_clean_tx_ring(interface->tx_ring[i]); fm10k_clean_tx_ring(interface->tx_ring[i]);
/* remove any stale timestamp buffers and free them */
skb_queue_purge(&interface->ts_tx_skb_queue);
} }
/** /**
...@@ -660,10 +657,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev) ...@@ -660,10 +657,6 @@ static netdev_tx_t fm10k_xmit_frame(struct sk_buff *skb, struct net_device *dev)
__skb_put(skb, pad_len); __skb_put(skb, pad_len);
} }
/* prepare packet for hardware time stamping */
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
fm10k_ts_tx_enqueue(interface, skb);
if (r_idx >= interface->num_tx_queues) if (r_idx >= interface->num_tx_queues)
r_idx %= interface->num_tx_queues; r_idx %= interface->num_tx_queues;
...@@ -884,7 +877,7 @@ static int __fm10k_uc_sync(struct net_device *dev, ...@@ -884,7 +877,7 @@ static int __fm10k_uc_sync(struct net_device *dev,
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
/* update table with current entries */ /* update table with current entries */
for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1;
vid < VLAN_N_VID; vid < VLAN_N_VID;
vid = fm10k_find_next_vlan(interface, vid)) { vid = fm10k_find_next_vlan(interface, vid)) {
err = hw->mac.ops.update_uc_addr(hw, glort, addr, err = hw->mac.ops.update_uc_addr(hw, glort, addr,
...@@ -947,7 +940,7 @@ static int __fm10k_mc_sync(struct net_device *dev, ...@@ -947,7 +940,7 @@ static int __fm10k_mc_sync(struct net_device *dev,
u16 vid, glort = interface->glort; u16 vid, glort = interface->glort;
/* update table with current entries */ /* update table with current entries */
for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1;
vid < VLAN_N_VID; vid < VLAN_N_VID;
vid = fm10k_find_next_vlan(interface, vid)) { vid = fm10k_find_next_vlan(interface, vid)) {
hw->mac.ops.update_mc_addr(hw, glort, addr, vid, sync); hw->mac.ops.update_mc_addr(hw, glort, addr, vid, sync);
...@@ -1002,11 +995,8 @@ static void fm10k_set_rx_mode(struct net_device *dev) ...@@ -1002,11 +995,8 @@ static void fm10k_set_rx_mode(struct net_device *dev)
} }
/* synchronize all of the addresses */ /* synchronize all of the addresses */
if (xcast_mode != FM10K_XCAST_MODE_PROMISC) {
__dev_uc_sync(dev, fm10k_uc_sync, fm10k_uc_unsync); __dev_uc_sync(dev, fm10k_uc_sync, fm10k_uc_unsync);
if (xcast_mode != FM10K_XCAST_MODE_ALLMULTI)
__dev_mc_sync(dev, fm10k_mc_sync, fm10k_mc_unsync); __dev_mc_sync(dev, fm10k_mc_sync, fm10k_mc_unsync);
}
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
} }
...@@ -1044,7 +1034,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1044,7 +1034,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
hw->mac.ops.update_vlan(hw, 0, 0, true); hw->mac.ops.update_vlan(hw, 0, 0, true);
/* update table with current entries */ /* update table with current entries */
for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 0; for (vid = hw->mac.default_vid ? fm10k_find_next_vlan(interface, 0) : 1;
vid < VLAN_N_VID; vid < VLAN_N_VID;
vid = fm10k_find_next_vlan(interface, vid)) { vid = fm10k_find_next_vlan(interface, vid)) {
hw->mac.ops.update_vlan(hw, vid, 0, true); hw->mac.ops.update_vlan(hw, vid, 0, true);
...@@ -1056,11 +1046,8 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1056,11 +1046,8 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode);
/* synchronize all of the addresses */ /* synchronize all of the addresses */
if (xcast_mode != FM10K_XCAST_MODE_PROMISC) {
__dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync); __dev_uc_sync(netdev, fm10k_uc_sync, fm10k_uc_unsync);
if (xcast_mode != FM10K_XCAST_MODE_ALLMULTI)
__dev_mc_sync(netdev, fm10k_mc_sync, fm10k_mc_unsync); __dev_mc_sync(netdev, fm10k_mc_sync, fm10k_mc_unsync);
}
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
...@@ -1213,18 +1200,6 @@ static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto, ...@@ -1213,18 +1200,6 @@ static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
return fm10k_setup_tc(dev, tc->tc); return fm10k_setup_tc(dev, tc->tc);
} }
static int fm10k_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
switch (cmd) {
case SIOCGHWTSTAMP:
return fm10k_get_ts_config(netdev, ifr);
case SIOCSHWTSTAMP:
return fm10k_set_ts_config(netdev, ifr);
default:
return -EOPNOTSUPP;
}
}
static void fm10k_assign_l2_accel(struct fm10k_intfc *interface, static void fm10k_assign_l2_accel(struct fm10k_intfc *interface,
struct fm10k_l2_accel *l2_accel) struct fm10k_l2_accel *l2_accel)
{ {
...@@ -1402,7 +1377,6 @@ static const struct net_device_ops fm10k_netdev_ops = { ...@@ -1402,7 +1377,6 @@ static const struct net_device_ops fm10k_netdev_ops = {
.ndo_get_vf_config = fm10k_ndo_get_vf_config, .ndo_get_vf_config = fm10k_ndo_get_vf_config,
.ndo_add_vxlan_port = fm10k_add_vxlan_port, .ndo_add_vxlan_port = fm10k_add_vxlan_port,
.ndo_del_vxlan_port = fm10k_del_vxlan_port, .ndo_del_vxlan_port = fm10k_del_vxlan_port,
.ndo_do_ioctl = fm10k_ioctl,
.ndo_dfwd_add_station = fm10k_dfwd_add_station, .ndo_dfwd_add_station = fm10k_dfwd_add_station,
.ndo_dfwd_del_station = fm10k_dfwd_del_station, .ndo_dfwd_del_station = fm10k_dfwd_del_station,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -209,9 +209,6 @@ static void fm10k_reinit(struct fm10k_intfc *interface) ...@@ -209,9 +209,6 @@ static void fm10k_reinit(struct fm10k_intfc *interface)
netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; netdev->features |= NETIF_F_HW_VLAN_CTAG_RX;
} }
/* reset clock */
fm10k_ts_reset(interface);
err = netif_running(netdev) ? fm10k_open(netdev) : 0; err = netif_running(netdev) ? fm10k_open(netdev) : 0;
if (err) if (err)
goto err_open; goto err_open;
...@@ -559,7 +556,6 @@ static void fm10k_service_task(struct work_struct *work) ...@@ -559,7 +556,6 @@ static void fm10k_service_task(struct work_struct *work)
/* tasks only run when interface is up */ /* tasks only run when interface is up */
fm10k_watchdog_subtask(interface); fm10k_watchdog_subtask(interface);
fm10k_check_hang_subtask(interface); fm10k_check_hang_subtask(interface);
fm10k_ts_tx_subtask(interface);
/* release lock on service events to allow scheduling next event */ /* release lock on service events to allow scheduling next event */
fm10k_service_event_complete(interface); fm10k_service_event_complete(interface);
...@@ -1204,25 +1200,6 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results, ...@@ -1204,25 +1200,6 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results,
return 0; return 0;
} }
static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info __always_unused *mbx)
{
struct fm10k_intfc *interface;
u64 timestamp;
s32 err;
err = fm10k_tlv_attr_get_u64(results[FM10K_1588_MSG_TIMESTAMP],
&timestamp);
if (err)
return err;
interface = container_of(hw, struct fm10k_intfc, hw);
fm10k_ts_tx_hwtstamp(interface, 0, timestamp);
return 0;
}
/* generic error handler for mailbox issues */ /* generic error handler for mailbox issues */
static s32 fm10k_mbx_error(struct fm10k_hw *hw, u32 **results, static s32 fm10k_mbx_error(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info __always_unused *mbx) struct fm10k_mbx_info __always_unused *mbx)
...@@ -1243,7 +1220,6 @@ static const struct fm10k_msg_data vf_mbx_data[] = { ...@@ -1243,7 +1220,6 @@ static const struct fm10k_msg_data vf_mbx_data[] = {
FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_mbx_mac_addr), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_mbx_mac_addr),
FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf), FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf),
FM10K_VF_MSG_1588_HANDLER(fm10k_1588_msg_vf),
FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error),
}; };
...@@ -1287,11 +1263,40 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results, ...@@ -1287,11 +1263,40 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results,
u32 dglort_map = hw->mac.dglort_map; u32 dglort_map = hw->mac.dglort_map;
s32 err; s32 err;
interface = container_of(hw, struct fm10k_intfc, hw);
err = fm10k_msg_err_pf(hw, results, mbx);
if (!err && hw->swapi.status) {
/* force link down for a reasonable delay */
interface->link_down_event = jiffies + (2 * HZ);
set_bit(__FM10K_LINK_DOWN, &interface->state);
/* reset dglort_map back to no config */
hw->mac.dglort_map = FM10K_DGLORTMAP_NONE;
fm10k_service_event_schedule(interface);
/* prevent overloading kernel message buffer */
if (interface->lport_map_failed)
return 0;
interface->lport_map_failed = true;
if (hw->swapi.status == FM10K_MSG_ERR_PEP_NOT_SCHEDULED)
dev_warn(&interface->pdev->dev,
"cannot obtain link because the host interface is configured for a PCIe host interface bandwidth of zero\n");
dev_warn(&interface->pdev->dev,
"request logical port map failed: %d\n",
hw->swapi.status);
return 0;
}
err = fm10k_msg_lport_map_pf(hw, results, mbx); err = fm10k_msg_lport_map_pf(hw, results, mbx);
if (err) if (err)
return err; return err;
interface = container_of(hw, struct fm10k_intfc, hw); interface->lport_map_failed = false;
/* we need to reset if port count was just updated */ /* we need to reset if port count was just updated */
if (dglort_map != hw->mac.dglort_map) if (dglort_map != hw->mac.dglort_map)
...@@ -1341,68 +1346,6 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results, ...@@ -1341,68 +1346,6 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results,
return 0; return 0;
} }
static s32 fm10k_1588_msg_pf(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info __always_unused *mbx)
{
struct fm10k_swapi_1588_timestamp timestamp;
struct fm10k_iov_data *iov_data;
struct fm10k_intfc *interface;
u16 sglort, vf_idx;
s32 err;
err = fm10k_tlv_attr_get_le_struct(
results[FM10K_PF_ATTR_ID_1588_TIMESTAMP],
&timestamp, sizeof(timestamp));
if (err)
return err;
interface = container_of(hw, struct fm10k_intfc, hw);
if (timestamp.dglort) {
fm10k_ts_tx_hwtstamp(interface, timestamp.dglort,
le64_to_cpu(timestamp.egress));
return 0;
}
/* either dglort or sglort must be set */
if (!timestamp.sglort)
return FM10K_ERR_PARAM;
/* verify GLORT is at least one of the ones we own */
sglort = le16_to_cpu(timestamp.sglort);
if (!fm10k_glort_valid_pf(hw, sglort))
return FM10K_ERR_PARAM;
if (sglort == interface->glort) {
fm10k_ts_tx_hwtstamp(interface, 0,
le64_to_cpu(timestamp.ingress));
return 0;
}
/* if there is no iov_data then there is no mailbox to process */
if (!ACCESS_ONCE(interface->iov_data))
return FM10K_ERR_PARAM;
rcu_read_lock();
/* notify VF if this timestamp belongs to it */
iov_data = interface->iov_data;
vf_idx = (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE) - sglort;
if (!iov_data || vf_idx >= iov_data->num_vfs) {
err = FM10K_ERR_PARAM;
goto err_unlock;
}
err = hw->iov.ops.report_timestamp(hw, &iov_data->vf_info[vf_idx],
le64_to_cpu(timestamp.ingress));
err_unlock:
rcu_read_unlock();
return err;
}
static const struct fm10k_msg_data pf_mbx_data[] = { static const struct fm10k_msg_data pf_mbx_data[] = {
FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf),
FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf),
...@@ -1410,7 +1353,6 @@ static const struct fm10k_msg_data pf_mbx_data[] = { ...@@ -1410,7 +1353,6 @@ static const struct fm10k_msg_data pf_mbx_data[] = {
FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf),
FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf),
FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_update_pvid), FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_update_pvid),
FM10K_PF_MSG_1588_TIMESTAMP_HANDLER(fm10k_1588_msg_pf),
FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_mbx_error),
}; };
...@@ -1789,18 +1731,9 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, ...@@ -1789,18 +1731,9 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
return -EIO; return -EIO;
} }
/* assign BAR 4 resources for use with PTP */
if (fm10k_read_reg(hw, FM10K_CTRL) & FM10K_CTRL_BAR4_ALLOWED)
interface->sw_addr = ioremap(pci_resource_start(pdev, 4),
pci_resource_len(pdev, 4));
hw->sw_addr = interface->sw_addr;
/* initialize DCBNL interface */ /* initialize DCBNL interface */
fm10k_dcbnl_set_ops(netdev); fm10k_dcbnl_set_ops(netdev);
/* Intitialize timestamp data */
fm10k_ts_init(interface);
/* set default ring sizes */ /* set default ring sizes */
interface->tx_ring_count = FM10K_DEFAULT_TXD; interface->tx_ring_count = FM10K_DEFAULT_TXD;
interface->rx_ring_count = FM10K_DEFAULT_RXD; interface->rx_ring_count = FM10K_DEFAULT_RXD;
...@@ -2018,9 +1951,6 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2018,9 +1951,6 @@ static int fm10k_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* kick off service timer now, even when interface is down */ /* kick off service timer now, even when interface is down */
mod_timer(&interface->service_timer, (HZ * 2) + jiffies); mod_timer(&interface->service_timer, (HZ * 2) + jiffies);
/* Register PTP interface */
fm10k_ptp_register(interface);
/* print warning for non-optimal configurations */ /* print warning for non-optimal configurations */
fm10k_slot_warn(interface); fm10k_slot_warn(interface);
...@@ -2077,9 +2007,6 @@ static void fm10k_remove(struct pci_dev *pdev) ...@@ -2077,9 +2007,6 @@ static void fm10k_remove(struct pci_dev *pdev)
if (netdev->reg_state == NETREG_REGISTERED) if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev); unregister_netdev(netdev);
/* cleanup timestamp handling */
fm10k_ptp_unregister(interface);
/* release VFs */ /* release VFs */
fm10k_iov_disable(pdev); fm10k_iov_disable(pdev);
...@@ -2152,9 +2079,6 @@ static int fm10k_resume(struct pci_dev *pdev) ...@@ -2152,9 +2079,6 @@ static int fm10k_resume(struct pci_dev *pdev)
/* reset statistics starting values */ /* reset statistics starting values */
hw->mac.ops.rebind_hw_stats(hw, &interface->stats); hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
/* reset clock */
fm10k_ts_reset(interface);
rtnl_lock(); rtnl_lock();
err = fm10k_init_queueing_scheme(interface); err = fm10k_init_queueing_scheme(interface);
...@@ -2271,6 +2195,8 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, ...@@ -2271,6 +2195,8 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev,
if (state == pci_channel_io_perm_failure) if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT; return PCI_ERS_RESULT_DISCONNECT;
rtnl_lock();
if (netif_running(netdev)) if (netif_running(netdev))
fm10k_close(netdev); fm10k_close(netdev);
...@@ -2279,7 +2205,7 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev, ...@@ -2279,7 +2205,7 @@ static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev,
/* free interrupts */ /* free interrupts */
fm10k_clear_queueing_scheme(interface); fm10k_clear_queueing_scheme(interface);
pci_disable_device(pdev); rtnl_unlock();
/* Request a slot reset. */ /* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET; return PCI_ERS_RESULT_NEED_RESET;
...@@ -2349,19 +2275,18 @@ static void fm10k_io_resume(struct pci_dev *pdev) ...@@ -2349,19 +2275,18 @@ static void fm10k_io_resume(struct pci_dev *pdev)
/* reset statistics starting values */ /* reset statistics starting values */
hw->mac.ops.rebind_hw_stats(hw, &interface->stats); hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
rtnl_lock();
err = fm10k_init_queueing_scheme(interface); err = fm10k_init_queueing_scheme(interface);
if (err) { if (err) {
dev_err(&interface->pdev->dev, dev_err(&interface->pdev->dev,
"init_queueing_scheme failed: %d\n", err); "init_queueing_scheme failed: %d\n", err);
return; goto unlock;
} }
/* reassociate interrupts */ /* reassociate interrupts */
fm10k_mbx_request_irq(interface); fm10k_mbx_request_irq(interface);
/* reset clock */
fm10k_ts_reset(interface);
if (netif_running(netdev)) if (netif_running(netdev))
err = fm10k_open(netdev); err = fm10k_open(netdev);
...@@ -2370,6 +2295,9 @@ static void fm10k_io_resume(struct pci_dev *pdev) ...@@ -2370,6 +2295,9 @@ static void fm10k_io_resume(struct pci_dev *pdev)
if (!err) if (!err)
netif_device_attach(netdev); netif_device_attach(netdev);
unlock:
rtnl_unlock();
} }
static const struct pci_error_handlers fm10k_err_handler = { static const struct pci_error_handlers fm10k_err_handler = {
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -219,8 +219,8 @@ static s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) ...@@ -219,8 +219,8 @@ static s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set)
/* VLAN multi-bit write: /* VLAN multi-bit write:
* The multi-bit write has several parts to it. * The multi-bit write has several parts to it.
* 3 2 1 0 * 24 16 8 0
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | RSVD0 | Length |C|RSVD0| VLAN ID | * | RSVD0 | Length |C|RSVD0| VLAN ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...@@ -488,6 +488,10 @@ static s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort, ...@@ -488,6 +488,10 @@ static s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort,
if (!fm10k_glort_valid_pf(hw, glort)) if (!fm10k_glort_valid_pf(hw, glort))
return FM10K_ERR_PARAM; return FM10K_ERR_PARAM;
/* reset multicast mode if deleting lport */
if (!enable)
fm10k_update_xcast_mode_pf(hw, glort, FM10K_XCAST_MODE_NONE);
/* construct the lport message from the 2 pieces of data we have */ /* construct the lport message from the 2 pieces of data we have */
lport_msg = ((u32)count << 16) | glort; lport_msg = ((u32)count << 16) | glort;
...@@ -864,9 +868,13 @@ static s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw, ...@@ -864,9 +868,13 @@ static s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw,
fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0); fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0);
fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0); fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0);
/* determine correct default VLAN ID */ /* Determine correct default VLAN ID. The FM10K_VLAN_OVERRIDE bit is
* used here to indicate to the VF that it will not have privilege to
* write VLAN_TABLE. All policy is enforced on the PF but this allows
* the VF to correctly report errors to userspace rqeuests.
*/
if (vf_info->pf_vid) if (vf_info->pf_vid)
vf_vid = vf_info->pf_vid | FM10K_VLAN_CLEAR; vf_vid = vf_info->pf_vid | FM10K_VLAN_OVERRIDE;
else else
vf_vid = vf_info->sw_vid; vf_vid = vf_info->sw_vid;
...@@ -1140,19 +1148,6 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, ...@@ -1140,19 +1148,6 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw,
fm10k_update_hw_stats_q(hw, q, idx, qpp); fm10k_update_hw_stats_q(hw, q, idx, qpp);
} }
static s32 fm10k_iov_report_timestamp_pf(struct fm10k_hw *hw,
struct fm10k_vf_info *vf_info,
u64 timestamp)
{
u32 msg[4];
/* generate port state response to notify VF it is not ready */
fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_1588);
fm10k_tlv_attr_put_u64(msg, FM10K_1588_MSG_TIMESTAMP, timestamp);
return vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg);
}
/** /**
* fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF
* @hw: Pointer to hardware structure * @hw: Pointer to hardware structure
...@@ -1633,6 +1628,8 @@ static s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready) ...@@ -1633,6 +1628,8 @@ static s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready)
/* This structure defines the attibutes to be parsed below */ /* This structure defines the attibutes to be parsed below */
const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = { const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = {
FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR,
sizeof(struct fm10k_swapi_error)),
FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP), FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP),
FM10K_TLV_ATTR_LAST FM10K_TLV_ATTR_LAST
}; };
...@@ -1773,89 +1770,6 @@ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results, ...@@ -1773,89 +1770,6 @@ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results,
return 0; return 0;
} }
const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[] = {
FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_1588_TIMESTAMP,
sizeof(struct fm10k_swapi_1588_timestamp)),
FM10K_TLV_ATTR_LAST
};
/* currently there is no shared 1588 timestamp handler */
/**
* fm10k_adjust_systime_pf - Adjust systime frequency
* @hw: pointer to hardware structure
* @ppb: adjustment rate in parts per billion
*
* This function will adjust the SYSTIME_CFG register contained in BAR 4
* if this function is supported for BAR 4 access. The adjustment amount
* is based on the parts per billion value provided and adjusted to a
* value based on parts per 2^48 clock cycles.
*
* If adjustment is not supported or the requested value is too large
* we will return an error.
**/
static s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb)
{
u64 systime_adjust;
/* if sw_addr is not set we don't have switch register access */
if (!hw->sw_addr)
return ppb ? FM10K_ERR_PARAM : 0;
/* we must convert the value from parts per billion to parts per
* 2^48 cycles. In addition I have opted to only use the 30 most
* significant bits of the adjustment value as the 8 least
* significant bits are located in another register and represent
* a value significantly less than a part per billion, the result
* of dropping the 8 least significant bits is that the adjustment
* value is effectively multiplied by 2^8 when we write it.
*
* As a result of all this the math for this breaks down as follows:
* ppb / 10^9 == adjust * 2^8 / 2^48
* If we solve this for adjust, and simplify it comes out as:
* ppb * 2^31 / 5^9 == adjust
*/
systime_adjust = (ppb < 0) ? -ppb : ppb;
systime_adjust <<= 31;
do_div(systime_adjust, 1953125);
/* verify the requested adjustment value is in range */
if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK)
return FM10K_ERR_PARAM;
if (ppb > 0)
systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE;
fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust);
return 0;
}
/**
* fm10k_read_systime_pf - Reads value of systime registers
* @hw: pointer to the hardware structure
*
* Function reads the content of 2 registers, combined to represent a 64 bit
* value measured in nanosecods. In order to guarantee the value is accurate
* we check the 32 most significant bits both before and after reading the
* 32 least significant bits to verify they didn't change as we were reading
* the registers.
**/
static u64 fm10k_read_systime_pf(struct fm10k_hw *hw)
{
u32 systime_l, systime_h, systime_tmp;
systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1);
do {
systime_tmp = systime_h;
systime_l = fm10k_read_reg(hw, FM10K_SYSTIME);
systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1);
} while (systime_tmp != systime_h);
return ((u64)systime_h << 32) | systime_l;
}
static const struct fm10k_msg_data fm10k_msg_data_pf[] = { static const struct fm10k_msg_data fm10k_msg_data_pf[] = {
FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf),
FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf),
...@@ -1885,8 +1799,6 @@ static const struct fm10k_mac_ops mac_ops_pf = { ...@@ -1885,8 +1799,6 @@ static const struct fm10k_mac_ops mac_ops_pf = {
.set_dma_mask = fm10k_set_dma_mask_pf, .set_dma_mask = fm10k_set_dma_mask_pf,
.get_fault = fm10k_get_fault_pf, .get_fault = fm10k_get_fault_pf,
.get_host_state = fm10k_get_host_state_pf, .get_host_state = fm10k_get_host_state_pf,
.adjust_systime = fm10k_adjust_systime_pf,
.read_systime = fm10k_read_systime_pf,
}; };
static const struct fm10k_iov_ops iov_ops_pf = { static const struct fm10k_iov_ops iov_ops_pf = {
...@@ -1898,7 +1810,6 @@ static const struct fm10k_iov_ops iov_ops_pf = { ...@@ -1898,7 +1810,6 @@ static const struct fm10k_iov_ops iov_ops_pf = {
.set_lport = fm10k_iov_set_lport_pf, .set_lport = fm10k_iov_set_lport_pf,
.reset_lport = fm10k_iov_reset_lport_pf, .reset_lport = fm10k_iov_reset_lport_pf,
.update_stats = fm10k_iov_update_stats_pf, .update_stats = fm10k_iov_update_stats_pf,
.report_timestamp = fm10k_iov_report_timestamp_pf,
}; };
static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw) static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw)
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -42,8 +42,6 @@ enum fm10k_pf_tlv_msg_id_v1 { ...@@ -42,8 +42,6 @@ enum fm10k_pf_tlv_msg_id_v1 {
FM10K_PF_MSG_ID_UPDATE_FLOW = 0x503, FM10K_PF_MSG_ID_UPDATE_FLOW = 0x503,
FM10K_PF_MSG_ID_DELETE_FLOW = 0x504, FM10K_PF_MSG_ID_DELETE_FLOW = 0x504,
FM10K_PF_MSG_ID_SET_FLOW_STATE = 0x505, FM10K_PF_MSG_ID_SET_FLOW_STATE = 0x505,
FM10K_PF_MSG_ID_GET_1588_INFO = 0x506,
FM10K_PF_MSG_ID_1588_TIMESTAMP = 0x701,
}; };
enum fm10k_pf_tlv_attr_id_v1 { enum fm10k_pf_tlv_attr_id_v1 {
...@@ -61,7 +59,6 @@ enum fm10k_pf_tlv_attr_id_v1 { ...@@ -61,7 +59,6 @@ enum fm10k_pf_tlv_attr_id_v1 {
FM10K_PF_ATTR_ID_DELETE_FLOW = 0x0B, FM10K_PF_ATTR_ID_DELETE_FLOW = 0x0B,
FM10K_PF_ATTR_ID_PORT = 0x0C, FM10K_PF_ATTR_ID_PORT = 0x0C,
FM10K_PF_ATTR_ID_UPDATE_PVID = 0x0D, FM10K_PF_ATTR_ID_UPDATE_PVID = 0x0D,
FM10K_PF_ATTR_ID_1588_TIMESTAMP = 0x10,
}; };
#define FM10K_MSG_LPORT_MAP_GLORT_SHIFT 0 #define FM10K_MSG_LPORT_MAP_GLORT_SHIFT 0
...@@ -74,6 +71,8 @@ enum fm10k_pf_tlv_attr_id_v1 { ...@@ -74,6 +71,8 @@ enum fm10k_pf_tlv_attr_id_v1 {
#define FM10K_MSG_UPDATE_PVID_PVID_SHIFT 16 #define FM10K_MSG_UPDATE_PVID_PVID_SHIFT 16
#define FM10K_MSG_UPDATE_PVID_PVID_SIZE 16 #define FM10K_MSG_UPDATE_PVID_PVID_SIZE 16
#define FM10K_MSG_ERR_PEP_NOT_SCHEDULED 280
/* The following data structures are overlayed directly onto TLV mailbox /* The following data structures are overlayed directly onto TLV mailbox
* messages, and must not break 4 byte alignment. Ensure the structures line * messages, and must not break 4 byte alignment. Ensure the structures line
* up correctly as per their TLV definition. * up correctly as per their TLV definition.
...@@ -100,13 +99,6 @@ struct fm10k_swapi_error { ...@@ -100,13 +99,6 @@ struct fm10k_swapi_error {
struct fm10k_global_table_data ffu; struct fm10k_global_table_data ffu;
} __aligned(4) __packed; } __aligned(4) __packed;
struct fm10k_swapi_1588_timestamp {
__le64 egress;
__le64 ingress;
__le16 dglort;
__le16 sglort;
} __aligned(4) __packed;
s32 fm10k_msg_lport_map_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); s32 fm10k_msg_lport_map_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *);
extern const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[]; extern const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[];
#define FM10K_PF_MSG_LPORT_MAP_HANDLER(func) \ #define FM10K_PF_MSG_LPORT_MAP_HANDLER(func) \
...@@ -122,11 +114,6 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[]; ...@@ -122,11 +114,6 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[];
#define FM10K_PF_MSG_ERR_HANDLER(msg, func) \ #define FM10K_PF_MSG_ERR_HANDLER(msg, func) \
FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func) FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func)
extern const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[];
#define FM10K_PF_MSG_1588_TIMESTAMP_HANDLER(func) \
FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_1588_TIMESTAMP, \
fm10k_1588_timestamp_msg_attr, func)
s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *);
s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **, s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **,
struct fm10k_mbx_info *); struct fm10k_mbx_info *);
......
/* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 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.
*
* 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/ptp_classify.h>
#include <linux/ptp_clock_kernel.h>
#include "fm10k.h"
#define FM10K_TS_TX_TIMEOUT (HZ * 15)
void fm10k_systime_to_hwtstamp(struct fm10k_intfc *interface,
struct skb_shared_hwtstamps *hwtstamp,
u64 systime)
{
unsigned long flags;
read_lock_irqsave(&interface->systime_lock, flags);
systime += interface->ptp_adjust;
read_unlock_irqrestore(&interface->systime_lock, flags);
hwtstamp->hwtstamp = ns_to_ktime(systime);
}
static struct sk_buff *fm10k_ts_tx_skb(struct fm10k_intfc *interface,
__le16 dglort)
{
struct sk_buff_head *list = &interface->ts_tx_skb_queue;
struct sk_buff *skb;
skb_queue_walk(list, skb) {
if (FM10K_CB(skb)->fi.w.dglort == dglort)
return skb;
}
return NULL;
}
void fm10k_ts_tx_enqueue(struct fm10k_intfc *interface, struct sk_buff *skb)
{
struct sk_buff_head *list = &interface->ts_tx_skb_queue;
struct sk_buff *clone;
unsigned long flags;
/* create clone for us to return on the Tx path */
clone = skb_clone_sk(skb);
if (!clone)
return;
FM10K_CB(clone)->ts_tx_timeout = jiffies + FM10K_TS_TX_TIMEOUT;
spin_lock_irqsave(&list->lock, flags);
/* attempt to locate any buffers with the same dglort,
* if none are present then insert skb in tail of list
*/
skb = fm10k_ts_tx_skb(interface, FM10K_CB(clone)->fi.w.dglort);
if (!skb) {
skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
__skb_queue_tail(list, clone);
}
spin_unlock_irqrestore(&list->lock, flags);
/* if list is already has one then we just free the clone */
if (skb)
dev_kfree_skb(clone);
}
void fm10k_ts_tx_hwtstamp(struct fm10k_intfc *interface, __le16 dglort,
u64 systime)
{
struct skb_shared_hwtstamps shhwtstamps;
struct sk_buff_head *list = &interface->ts_tx_skb_queue;
struct sk_buff *skb;
unsigned long flags;
spin_lock_irqsave(&list->lock, flags);
/* attempt to locate and pull the sk_buff out of the list */
skb = fm10k_ts_tx_skb(interface, dglort);
if (skb)
__skb_unlink(skb, list);
spin_unlock_irqrestore(&list->lock, flags);
/* if not found do nothing */
if (!skb)
return;
/* timestamp the sk_buff and free out copy */
fm10k_systime_to_hwtstamp(interface, &shhwtstamps, systime);
skb_tstamp_tx(skb, &shhwtstamps);
dev_kfree_skb_any(skb);
}
void fm10k_ts_tx_subtask(struct fm10k_intfc *interface)
{
struct sk_buff_head *list = &interface->ts_tx_skb_queue;
struct sk_buff *skb, *tmp;
unsigned long flags;
/* If we're down or resetting, just bail */
if (test_bit(__FM10K_DOWN, &interface->state) ||
test_bit(__FM10K_RESETTING, &interface->state))
return;
spin_lock_irqsave(&list->lock, flags);
/* walk though the list and flush any expired timestamp packets */
skb_queue_walk_safe(list, skb, tmp) {
if (!time_is_after_jiffies(FM10K_CB(skb)->ts_tx_timeout))
continue;
__skb_unlink(skb, list);
kfree_skb(skb);
interface->tx_hwtstamp_timeouts++;
}
spin_unlock_irqrestore(&list->lock, flags);
}
static u64 fm10k_systime_read(struct fm10k_intfc *interface)
{
struct fm10k_hw *hw = &interface->hw;
return hw->mac.ops.read_systime(hw);
}
void fm10k_ts_reset(struct fm10k_intfc *interface)
{
s64 ns = ktime_to_ns(ktime_get_real());
unsigned long flags;
/* reinitialize the clock */
write_lock_irqsave(&interface->systime_lock, flags);
interface->ptp_adjust = fm10k_systime_read(interface) - ns;
write_unlock_irqrestore(&interface->systime_lock, flags);
}
void fm10k_ts_init(struct fm10k_intfc *interface)
{
/* Initialize lock protecting systime access */
rwlock_init(&interface->systime_lock);
/* Initialize skb queue for pending timestamp requests */
skb_queue_head_init(&interface->ts_tx_skb_queue);
/* reset the clock to current kernel time */
fm10k_ts_reset(interface);
}
/**
* fm10k_get_ts_config - get current hardware timestamping configuration
* @netdev: network interface device structure
* @ifreq: ioctl data
*
* This function returns the current timestamping settings. Rather than
* attempt to deconstruct registers to fill in the values, simply keep a copy
* of the old settings around, and return a copy when requested.
*/
int fm10k_get_ts_config(struct net_device *netdev, struct ifreq *ifr)
{
struct fm10k_intfc *interface = netdev_priv(netdev);
struct hwtstamp_config *config = &interface->ts_config;
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
-EFAULT : 0;
}
/**
* fm10k_set_ts_config - control hardware time stamping
* @netdev: network interface device structure
* @ifreq: ioctl data
*
* Outgoing time stamping can be enabled and disabled. Play nice and
* disable it when requested, although it shouldn't cause 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".
*
* Since hardware always timestamps Path delay packets when timestamping V2
* packets, regardless of the type specified in the register, only use V2
* Event mode. This more accurately tells the user what the hardware is going
* to do anyways.
*/
int fm10k_set_ts_config(struct net_device *netdev, struct ifreq *ifr)
{
struct fm10k_intfc *interface = netdev_priv(netdev);
struct hwtstamp_config ts_config;
if (copy_from_user(&ts_config, ifr->ifr_data, sizeof(ts_config)))
return -EFAULT;
/* reserved for future extensions */
if (ts_config.flags)
return -EINVAL;
switch (ts_config.tx_type) {
case HWTSTAMP_TX_OFF:
break;
case HWTSTAMP_TX_ON:
/* we likely need some check here to see if this is supported */
break;
default:
return -ERANGE;
}
switch (ts_config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
interface->flags &= ~FM10K_FLAG_RX_TS_ENABLED;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
case HWTSTAMP_FILTER_ALL:
interface->flags |= FM10K_FLAG_RX_TS_ENABLED;
ts_config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
default:
return -ERANGE;
}
/* save these settings for future reference */
interface->ts_config = ts_config;
return copy_to_user(ifr->ifr_data, &ts_config, sizeof(ts_config)) ?
-EFAULT : 0;
}
static int fm10k_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
{
struct fm10k_intfc *interface;
struct fm10k_hw *hw;
int err;
interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
hw = &interface->hw;
err = hw->mac.ops.adjust_systime(hw, ppb);
/* the only error we should see is if the value is out of range */
return (err == FM10K_ERR_PARAM) ? -ERANGE : err;
}
static int fm10k_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct fm10k_intfc *interface;
unsigned long flags;
interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
write_lock_irqsave(&interface->systime_lock, flags);
interface->ptp_adjust += delta;
write_unlock_irqrestore(&interface->systime_lock, flags);
return 0;
}
static int fm10k_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
struct fm10k_intfc *interface;
unsigned long flags;
u64 now;
interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
read_lock_irqsave(&interface->systime_lock, flags);
now = fm10k_systime_read(interface) + interface->ptp_adjust;
read_unlock_irqrestore(&interface->systime_lock, flags);
*ts = ns_to_timespec64(now);
return 0;
}
static int fm10k_ptp_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
struct fm10k_intfc *interface;
unsigned long flags;
u64 ns = timespec64_to_ns(ts);
interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
write_lock_irqsave(&interface->systime_lock, flags);
interface->ptp_adjust = fm10k_systime_read(interface) - ns;
write_unlock_irqrestore(&interface->systime_lock, flags);
return 0;
}
static int fm10k_ptp_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq,
int __always_unused on)
{
struct ptp_clock_time *t = &rq->perout.period;
struct fm10k_intfc *interface;
struct fm10k_hw *hw;
u64 period;
u32 step;
/* we can only support periodic output */
if (rq->type != PTP_CLK_REQ_PEROUT)
return -EINVAL;
/* verify the requested channel is there */
if (rq->perout.index >= ptp->n_per_out)
return -EINVAL;
/* we cannot enforce start time as there is no
* mechanism for that in the hardware, we can only control
* the period.
*/
/* we cannot support periods greater than 4 seconds due to reg limit */
if (t->sec > 4 || t->sec < 0)
return -ERANGE;
interface = container_of(ptp, struct fm10k_intfc, ptp_caps);
hw = &interface->hw;
/* we simply cannot support the operation if we don't have BAR4 */
if (!hw->sw_addr)
return -ENOTSUPP;
/* convert to unsigned 64b ns, verify we can put it in a 32b register */
period = t->sec * 1000000000LL + t->nsec;
/* determine the minimum size for period */
step = 2 * (fm10k_read_reg(hw, FM10K_SYSTIME_CFG) &
FM10K_SYSTIME_CFG_STEP_MASK);
/* verify the value is in range supported by hardware */
if ((period && (period < step)) || (period > U32_MAX))
return -ERANGE;
/* notify hardware of request to being sending pulses */
fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_PULSE(rq->perout.index),
(u32)period);
return 0;
}
static struct ptp_pin_desc fm10k_ptp_pd[2] = {
{
.name = "IEEE1588_PULSE0",
.index = 0,
.func = PTP_PF_PEROUT,
.chan = 0
},
{
.name = "IEEE1588_PULSE1",
.index = 1,
.func = PTP_PF_PEROUT,
.chan = 1
}
};
static int fm10k_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
enum ptp_pin_function func, unsigned int chan)
{
/* verify the requested pin is there */
if (pin >= ptp->n_pins || !ptp->pin_config)
return -EINVAL;
/* enforce locked channels, no changing them */
if (chan != ptp->pin_config[pin].chan)
return -EINVAL;
/* we want to keep the functions locked as well */
if (func != ptp->pin_config[pin].func)
return -EINVAL;
return 0;
}
void fm10k_ptp_register(struct fm10k_intfc *interface)
{
struct ptp_clock_info *ptp_caps = &interface->ptp_caps;
struct device *dev = &interface->pdev->dev;
struct ptp_clock *ptp_clock;
snprintf(ptp_caps->name, sizeof(ptp_caps->name),
"%s", interface->netdev->name);
ptp_caps->owner = THIS_MODULE;
/* This math is simply the inverse of the math in
* fm10k_adjust_systime_pf applied to an adjustment value
* of 2^30 - 1 which is the maximum value of the register:
* max_ppb == ((2^30 - 1) * 5^9) / 2^31
*/
ptp_caps->max_adj = 976562;
ptp_caps->adjfreq = fm10k_ptp_adjfreq;
ptp_caps->adjtime = fm10k_ptp_adjtime;
ptp_caps->gettime64 = fm10k_ptp_gettime;
ptp_caps->settime64 = fm10k_ptp_settime;
/* provide pins if BAR4 is accessible */
if (interface->sw_addr) {
/* enable periodic outputs */
ptp_caps->n_per_out = 2;
ptp_caps->enable = fm10k_ptp_enable;
/* enable clock pins */
ptp_caps->verify = fm10k_ptp_verify;
ptp_caps->n_pins = 2;
ptp_caps->pin_config = fm10k_ptp_pd;
}
ptp_clock = ptp_clock_register(ptp_caps, dev);
if (IS_ERR(ptp_clock)) {
ptp_clock = NULL;
dev_err(dev, "ptp_clock_register failed\n");
} else {
dev_info(dev, "registered PHC device %s\n", ptp_caps->name);
}
interface->ptp_clock = ptp_clock;
}
void fm10k_ptp_unregister(struct fm10k_intfc *interface)
{
struct ptp_clock *ptp_clock = interface->ptp_clock;
struct device *dev = &interface->pdev->dev;
if (!ptp_clock)
return;
interface->ptp_clock = NULL;
ptp_clock_unregister(ptp_clock);
dev_info(dev, "removed PHC %s\n", interface->ptp_caps.name);
}
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -481,7 +481,8 @@ static s32 fm10k_tlv_attr_validate(u32 *attr, ...@@ -481,7 +481,8 @@ static s32 fm10k_tlv_attr_validate(u32 *attr,
* up into an array of pointers stored in results. The function will * up into an array of pointers stored in results. The function will
* return FM10K_ERR_PARAM on any input or message error, * return FM10K_ERR_PARAM on any input or message error,
* FM10K_NOT_IMPLEMENTED for any attribute that is outside of the array * FM10K_NOT_IMPLEMENTED for any attribute that is outside of the array
* and 0 on success. * and 0 on success. Any attributes not found in tlv_attr will be silently
* ignored.
**/ **/
static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results, static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results,
const struct fm10k_tlv_attr *tlv_attr) const struct fm10k_tlv_attr *tlv_attr)
...@@ -518,14 +519,15 @@ static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results, ...@@ -518,14 +519,15 @@ static s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results,
while (offset < len) { while (offset < len) {
attr_id = *attr & FM10K_TLV_ID_MASK; attr_id = *attr & FM10K_TLV_ID_MASK;
if (attr_id < FM10K_TLV_RESULTS_MAX) if (attr_id >= FM10K_TLV_RESULTS_MAX)
err = fm10k_tlv_attr_validate(attr, tlv_attr); return FM10K_NOT_IMPLEMENTED;
else
err = FM10K_NOT_IMPLEMENTED;
if (err < 0) err = fm10k_tlv_attr_validate(attr, tlv_attr);
if (err == FM10K_NOT_IMPLEMENTED)
; /* silently ignore non-implemented attributes */
else if (err)
return err; return err;
if (!err) else
results[attr_id] = attr; results[attr_id] = attr;
/* update offset */ /* update offset */
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -225,11 +225,6 @@ struct fm10k_hw; ...@@ -225,11 +225,6 @@ struct fm10k_hw;
#define FM10K_STATS_LOOPBACK_DROP 0x3806 #define FM10K_STATS_LOOPBACK_DROP 0x3806
#define FM10K_STATS_NODESC_DROP 0x3807 #define FM10K_STATS_NODESC_DROP 0x3807
/* Timesync registers */
#define FM10K_SYSTIME 0x3814
#define FM10K_SYSTIME_CFG 0x3818
#define FM10K_SYSTIME_CFG_STEP_MASK 0x0000000F
/* PCIe state registers */ /* PCIe state registers */
#define FM10K_PHYADDR 0x381C #define FM10K_PHYADDR 0x381C
...@@ -355,6 +350,7 @@ struct fm10k_hw; ...@@ -355,6 +350,7 @@ struct fm10k_hw;
#define FM10K_VLAN_TABLE_VSI_MAX 64 #define FM10K_VLAN_TABLE_VSI_MAX 64
#define FM10K_VLAN_LENGTH_SHIFT 16 #define FM10K_VLAN_LENGTH_SHIFT 16
#define FM10K_VLAN_CLEAR BIT(15) #define FM10K_VLAN_CLEAR BIT(15)
#define FM10K_VLAN_OVERRIDE FM10K_VLAN_CLEAR
#define FM10K_VLAN_ALL \ #define FM10K_VLAN_ALL \
((FM10K_VLAN_TABLE_VID_MAX - 1) << FM10K_VLAN_LENGTH_SHIFT) ((FM10K_VLAN_TABLE_VID_MAX - 1) << FM10K_VLAN_LENGTH_SHIFT)
...@@ -381,12 +377,6 @@ struct fm10k_hw; ...@@ -381,12 +377,6 @@ struct fm10k_hw;
#define FM10K_VFSYSTIME 0x00040 #define FM10K_VFSYSTIME 0x00040
#define FM10K_VFITR(_n) ((_n) + 0x00060) #define FM10K_VFITR(_n) ((_n) + 0x00060)
/* Registers contained in BAR 4 for Switch management */
#define FM10K_SW_SYSTIME_ADJUST 0x0224D
#define FM10K_SW_SYSTIME_ADJUST_MASK 0x3FFFFFFF
#define FM10K_SW_SYSTIME_ADJUST_DIR_POSITIVE 0x80000000
#define FM10K_SW_SYSTIME_PULSE(_n) ((_n) + 0x02252)
enum fm10k_int_source { enum fm10k_int_source {
fm10k_int_mailbox = 0, fm10k_int_mailbox = 0,
fm10k_int_pcie_fault = 1, fm10k_int_pcie_fault = 1,
...@@ -550,8 +540,6 @@ struct fm10k_mac_ops { ...@@ -550,8 +540,6 @@ struct fm10k_mac_ops {
struct fm10k_dglort_cfg *); struct fm10k_dglort_cfg *);
void (*set_dma_mask)(struct fm10k_hw *, u64); void (*set_dma_mask)(struct fm10k_hw *, u64);
s32 (*get_fault)(struct fm10k_hw *, int, struct fm10k_fault *); s32 (*get_fault)(struct fm10k_hw *, int, struct fm10k_fault *);
s32 (*adjust_systime)(struct fm10k_hw *, s32 ppb);
u64 (*read_systime)(struct fm10k_hw *);
}; };
enum fm10k_mac_type { enum fm10k_mac_type {
...@@ -643,7 +631,6 @@ struct fm10k_iov_ops { ...@@ -643,7 +631,6 @@ struct fm10k_iov_ops {
s32 (*set_lport)(struct fm10k_hw *, struct fm10k_vf_info *, u16, u8); s32 (*set_lport)(struct fm10k_hw *, struct fm10k_vf_info *, u16, u8);
void (*reset_lport)(struct fm10k_hw *, struct fm10k_vf_info *); void (*reset_lport)(struct fm10k_hw *, struct fm10k_vf_info *);
void (*update_stats)(struct fm10k_hw *, struct fm10k_hw_stats_q *, u16); void (*update_stats)(struct fm10k_hw *, struct fm10k_hw_stats_q *, u16);
s32 (*report_timestamp)(struct fm10k_hw *, struct fm10k_vf_info *, u64);
}; };
struct fm10k_iov_info { struct fm10k_iov_info {
...@@ -667,7 +654,6 @@ struct fm10k_info { ...@@ -667,7 +654,6 @@ struct fm10k_info {
struct fm10k_hw { struct fm10k_hw {
u32 __iomem *hw_addr; u32 __iomem *hw_addr;
u32 __iomem *sw_addr;
void *back; void *back;
struct fm10k_mac_info mac; struct fm10k_mac_info mac;
struct fm10k_bus_info bus; struct fm10k_bus_info bus;
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2015 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -188,7 +188,7 @@ static s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) ...@@ -188,7 +188,7 @@ static s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set)
if (vsi) if (vsi)
return FM10K_ERR_PARAM; return FM10K_ERR_PARAM;
/* verify upper 4 bits of vid and length are 0 */ /* clever trick to verify reserved bits in both vid and length */
if ((vid << 16 | vid) >> 28) if ((vid << 16 | vid) >> 28)
return FM10K_ERR_PARAM; return FM10K_ERR_PARAM;
...@@ -228,7 +228,7 @@ s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results, ...@@ -228,7 +228,7 @@ s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results,
ether_addr_copy(hw->mac.perm_addr, perm_addr); ether_addr_copy(hw->mac.perm_addr, perm_addr);
hw->mac.default_vid = vid & (FM10K_VLAN_TABLE_VID_MAX - 1); hw->mac.default_vid = vid & (FM10K_VLAN_TABLE_VID_MAX - 1);
hw->mac.vlan_override = !!(vid & FM10K_VLAN_CLEAR); hw->mac.vlan_override = !!(vid & FM10K_VLAN_OVERRIDE);
return 0; return 0;
} }
...@@ -451,13 +451,6 @@ static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode) ...@@ -451,13 +451,6 @@ static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode)
return mbx->ops.enqueue_tx(hw, mbx, msg); return mbx->ops.enqueue_tx(hw, mbx, msg);
} }
const struct fm10k_tlv_attr fm10k_1588_msg_attr[] = {
FM10K_TLV_ATTR_U64(FM10K_1588_MSG_TIMESTAMP),
FM10K_TLV_ATTR_LAST
};
/* currently there is no shared 1588 timestamp handler */
/** /**
* fm10k_update_hw_stats_vf - Updates hardware related statistics of VF * fm10k_update_hw_stats_vf - Updates hardware related statistics of VF
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
...@@ -509,52 +502,6 @@ static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw, ...@@ -509,52 +502,6 @@ static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw,
return 0; return 0;
} }
/**
* fm10k_adjust_systime_vf - Adjust systime frequency
* @hw: pointer to hardware structure
* @ppb: adjustment rate in parts per billion
*
* This function takes an adjustment rate in parts per billion and will
* verify that this value is 0 as the VF cannot support adjusting the
* systime clock.
*
* If the ppb value is non-zero the return is ERR_PARAM else success
**/
static s32 fm10k_adjust_systime_vf(struct fm10k_hw *hw, s32 ppb)
{
/* The VF cannot adjust the clock frequency, however it should
* already have a syntonic clock with whichever host interface is
* running as the master for the host interface clock domain so
* there should be not frequency adjustment necessary.
*/
return ppb ? FM10K_ERR_PARAM : 0;
}
/**
* fm10k_read_systime_vf - Reads value of systime registers
* @hw: pointer to the hardware structure
*
* Function reads the content of 2 registers, combined to represent a 64 bit
* value measured in nanoseconds. In order to guarantee the value is accurate
* we check the 32 most significant bits both before and after reading the
* 32 least significant bits to verify they didn't change as we were reading
* the registers.
**/
static u64 fm10k_read_systime_vf(struct fm10k_hw *hw)
{
u32 systime_l, systime_h, systime_tmp;
systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
do {
systime_tmp = systime_h;
systime_l = fm10k_read_reg(hw, FM10K_VFSYSTIME);
systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
} while (systime_tmp != systime_h);
return ((u64)systime_h << 32) | systime_l;
}
static const struct fm10k_msg_data fm10k_msg_data_vf[] = { static const struct fm10k_msg_data fm10k_msg_data_vf[] = {
FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf),
...@@ -579,8 +526,6 @@ static const struct fm10k_mac_ops mac_ops_vf = { ...@@ -579,8 +526,6 @@ static const struct fm10k_mac_ops mac_ops_vf = {
.rebind_hw_stats = fm10k_rebind_hw_stats_vf, .rebind_hw_stats = fm10k_rebind_hw_stats_vf,
.configure_dglort_map = fm10k_configure_dglort_map_vf, .configure_dglort_map = fm10k_configure_dglort_map_vf,
.get_host_state = fm10k_get_host_state_generic, .get_host_state = fm10k_get_host_state_generic,
.adjust_systime = fm10k_adjust_systime_vf,
.read_systime = fm10k_read_systime_vf,
}; };
static s32 fm10k_get_invariants_vf(struct fm10k_hw *hw) static s32 fm10k_get_invariants_vf(struct fm10k_hw *hw)
......
/* Intel Ethernet Switch Host Interface Driver /* Intel(R) Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2016 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -29,7 +29,6 @@ enum fm10k_vf_tlv_msg_id { ...@@ -29,7 +29,6 @@ enum fm10k_vf_tlv_msg_id {
FM10K_VF_MSG_ID_MSIX, FM10K_VF_MSG_ID_MSIX,
FM10K_VF_MSG_ID_MAC_VLAN, FM10K_VF_MSG_ID_MAC_VLAN,
FM10K_VF_MSG_ID_LPORT_STATE, FM10K_VF_MSG_ID_LPORT_STATE,
FM10K_VF_MSG_ID_1588,
FM10K_VF_MSG_ID_MAX, FM10K_VF_MSG_ID_MAX,
}; };
...@@ -49,11 +48,6 @@ enum fm10k_tlv_lport_state_attr_id { ...@@ -49,11 +48,6 @@ enum fm10k_tlv_lport_state_attr_id {
FM10K_LPORT_STATE_MSG_MAX FM10K_LPORT_STATE_MSG_MAX
}; };
enum fm10k_tlv_1588_attr_id {
FM10K_1588_MSG_TIMESTAMP,
FM10K_1588_MSG_MAX
};
#define FM10K_VF_MSG_MSIX_HANDLER(func) \ #define FM10K_VF_MSG_MSIX_HANDLER(func) \
FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MSIX, NULL, func) FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MSIX, NULL, func)
...@@ -70,9 +64,5 @@ extern const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[]; ...@@ -70,9 +64,5 @@ extern const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[];
FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_LPORT_STATE, \ FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_LPORT_STATE, \
fm10k_lport_state_msg_attr, func) fm10k_lport_state_msg_attr, func)
extern const struct fm10k_tlv_attr fm10k_1588_msg_attr[];
#define FM10K_VF_MSG_1588_HANDLER(func) \
FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_1588, fm10k_1588_msg_attr, func)
extern const struct fm10k_info fm10k_vf_info; extern const struct fm10k_info fm10k_vf_info;
#endif /* _FM10K_VF_H */ #endif /* _FM10K_VF_H */
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