Commit 9f915141 authored by David S. Miller's avatar David S. Miller

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

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2015-04-14

This series contains updates to fm10k only.

Fixed transmit statistics which was actually using values from the
receive ring, instead of the transmit ring.  Fixed up spelling mistakes
in code comments and resolved unused argument warnings.  Added support
for netconsole.  Fixed up statistic reporting so that we are only
reporting from actual queues as well as display PF only stats for
just the PF and not the VF.  Also fixed an issue that when returning
virtualization queues from the VF back to the PF, we were retaining
the VF rate limiter.

Fixed up the driver to use a separate workqueue, which helps reduce
and stabilize latency between scheduling the work in our interrupt and
actually performing the work.

Fixed a bug where the VF tried to set a multicast address before
requesting the required xcast mode.

Fix VF multicast update since VFs were being improperly added to the
switch's mutlicast group.  The error stems from the fact that incorrect
arguments were passed to the update_mc_addr().

Thanks to Alex Duyck for the extensive review.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bae97d84 f4f88c6d
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -235,6 +235,9 @@ struct fm10k_vxlan_port { ...@@ -235,6 +235,9 @@ struct fm10k_vxlan_port {
__be16 port; __be16 port;
}; };
/* one work queue for entire driver */
extern struct workqueue_struct *fm10k_workqueue;
struct fm10k_intfc { struct fm10k_intfc {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct net_device *netdev; struct net_device *netdev;
...@@ -266,7 +269,6 @@ struct fm10k_intfc { ...@@ -266,7 +269,6 @@ struct fm10k_intfc {
u64 tx_csum_errors; u64 tx_csum_errors;
u64 alloc_failed; u64 alloc_failed;
u64 rx_csum_errors; u64 rx_csum_errors;
u64 rx_errors;
u64 tx_bytes_nic; u64 tx_bytes_nic;
u64 tx_packets_nic; u64 tx_packets_nic;
...@@ -458,6 +460,9 @@ void fm10k_down(struct fm10k_intfc *interface); ...@@ -458,6 +460,9 @@ void fm10k_down(struct fm10k_intfc *interface);
void fm10k_update_stats(struct fm10k_intfc *interface); void fm10k_update_stats(struct fm10k_intfc *interface);
void fm10k_service_event_schedule(struct fm10k_intfc *interface); void fm10k_service_event_schedule(struct fm10k_intfc *interface);
void fm10k_update_rx_drop_en(struct fm10k_intfc *interface); void fm10k_update_rx_drop_en(struct fm10k_intfc *interface);
#ifdef CONFIG_NET_POLL_CONTROLLER
void fm10k_netpoll(struct net_device *netdev);
#endif
/* Netdev */ /* Netdev */
struct net_device *fm10k_alloc_netdev(void); struct net_device *fm10k_alloc_netdev(void);
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -128,7 +128,7 @@ static int fm10k_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) ...@@ -128,7 +128,7 @@ static int fm10k_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
* *
* Returns that we support only IEEE DCB for this interface * Returns that we support only IEEE DCB for this interface
**/ **/
static u8 fm10k_dcbnl_getdcbx(struct net_device *dev) static u8 fm10k_dcbnl_getdcbx(struct net_device __always_unused *dev)
{ {
return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
} }
...@@ -140,7 +140,7 @@ static u8 fm10k_dcbnl_getdcbx(struct net_device *dev) ...@@ -140,7 +140,7 @@ static u8 fm10k_dcbnl_getdcbx(struct net_device *dev)
* *
* Returns error on attempt to enable anything but IEEE DCB for this interface * Returns error on attempt to enable anything but IEEE DCB for this interface
**/ **/
static u8 fm10k_dcbnl_setdcbx(struct net_device *dev, u8 mode) static u8 fm10k_dcbnl_setdcbx(struct net_device __always_unused *dev, u8 mode)
{ {
return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0; return (mode != (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE)) ? 1 : 0;
} }
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -36,14 +36,16 @@ static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos) ...@@ -36,14 +36,16 @@ static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos)
return (*pos < ring->count) ? pos : NULL; return (*pos < ring->count) ? pos : NULL;
} }
static void *fm10k_dbg_desc_seq_next(struct seq_file *s, void *v, loff_t *pos) static void *fm10k_dbg_desc_seq_next(struct seq_file *s,
void __always_unused *v, loff_t *pos)
{ {
struct fm10k_ring *ring = s->private; struct fm10k_ring *ring = s->private;
return (++(*pos) < ring->count) ? pos : NULL; return (++(*pos) < ring->count) ? pos : NULL;
} }
static void fm10k_dbg_desc_seq_stop(struct seq_file *s, void *v) static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s,
__always_unused void *v)
{ {
/* Do nothing. */ /* Do nothing. */
} }
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -57,13 +57,12 @@ static const struct fm10k_stats fm10k_gstrings_net_stats[] = { ...@@ -57,13 +57,12 @@ static const struct fm10k_stats fm10k_gstrings_net_stats[] = {
.stat_offset = offsetof(struct fm10k_intfc, _stat) \ .stat_offset = offsetof(struct fm10k_intfc, _stat) \
} }
static const struct fm10k_stats fm10k_gstrings_stats[] = { static const struct fm10k_stats fm10k_gstrings_global_stats[] = {
FM10K_STAT("tx_restart_queue", restart_queue), FM10K_STAT("tx_restart_queue", restart_queue),
FM10K_STAT("tx_busy", tx_busy), FM10K_STAT("tx_busy", tx_busy),
FM10K_STAT("tx_csum_errors", tx_csum_errors), FM10K_STAT("tx_csum_errors", tx_csum_errors),
FM10K_STAT("rx_alloc_failed", alloc_failed), FM10K_STAT("rx_alloc_failed", alloc_failed),
FM10K_STAT("rx_csum_errors", rx_csum_errors), FM10K_STAT("rx_csum_errors", rx_csum_errors),
FM10K_STAT("rx_errors", rx_errors),
FM10K_STAT("tx_packets_nic", tx_packets_nic), FM10K_STAT("tx_packets_nic", tx_packets_nic),
FM10K_STAT("tx_bytes_nic", tx_bytes_nic), FM10K_STAT("tx_bytes_nic", tx_bytes_nic),
...@@ -73,38 +72,42 @@ static const struct fm10k_stats fm10k_gstrings_stats[] = { ...@@ -73,38 +72,42 @@ static const struct fm10k_stats fm10k_gstrings_stats[] = {
FM10K_STAT("rx_overrun_pf", rx_overrun_pf), FM10K_STAT("rx_overrun_pf", rx_overrun_pf),
FM10K_STAT("rx_overrun_vf", rx_overrun_vf), FM10K_STAT("rx_overrun_vf", rx_overrun_vf),
FM10K_STAT("timeout", stats.timeout.count),
FM10K_STAT("ur", stats.ur.count),
FM10K_STAT("ca", stats.ca.count),
FM10K_STAT("um", stats.um.count),
FM10K_STAT("xec", stats.xec.count),
FM10K_STAT("vlan_drop", stats.vlan_drop.count),
FM10K_STAT("loopback_drop", stats.loopback_drop.count),
FM10K_STAT("nodesc_drop", stats.nodesc_drop.count),
FM10K_STAT("swapi_status", hw.swapi.status), FM10K_STAT("swapi_status", hw.swapi.status),
FM10K_STAT("mac_rules_used", hw.swapi.mac.used), FM10K_STAT("mac_rules_used", hw.swapi.mac.used),
FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail), FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail),
FM10K_STAT("mbx_tx_busy", hw.mbx.tx_busy), FM10K_STAT("mbx_tx_busy", hw.mbx.tx_busy),
FM10K_STAT("mbx_tx_dropped", hw.mbx.tx_dropped), FM10K_STAT("mbx_tx_oversized", hw.mbx.tx_dropped),
FM10K_STAT("mbx_tx_messages", hw.mbx.tx_messages), FM10K_STAT("mbx_tx_messages", hw.mbx.tx_messages),
FM10K_STAT("mbx_tx_dwords", hw.mbx.tx_dwords), FM10K_STAT("mbx_tx_dwords", hw.mbx.tx_dwords),
FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages), FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages),
FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords), FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords),
FM10K_STAT("mbx_rx_parse_err", hw.mbx.rx_parse_err), FM10K_STAT("mbx_rx_parse_err", hw.mbx.rx_parse_err),
FM10K_STAT("tx_hang_count", tx_timeout_count),
FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
}; };
#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_stats) static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {
FM10K_STAT("timeout", stats.timeout.count),
FM10K_STAT("ur", stats.ur.count),
FM10K_STAT("ca", stats.ca.count),
FM10K_STAT("um", stats.um.count),
FM10K_STAT("xec", stats.xec.count),
FM10K_STAT("vlan_drop", stats.vlan_drop.count),
FM10K_STAT("loopback_drop", stats.loopback_drop.count),
FM10K_STAT("nodesc_drop", stats.nodesc_drop.count),
};
#define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats)
#define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats)
#define FM10K_QUEUE_STATS_LEN \ #define FM10K_QUEUE_STATS_LEN(_n) \
(MAX_QUEUES * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64))) ( (_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64)))
#define FM10K_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \ #define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \
FM10K_NETDEV_STATS_LEN + \ FM10K_NETDEV_STATS_LEN)
FM10K_QUEUE_STATS_LEN)
static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = { static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = {
"Mailbox test (on/offline)" "Mailbox test (on/offline)"
...@@ -117,9 +120,9 @@ enum fm10k_self_test_types { ...@@ -117,9 +120,9 @@ enum fm10k_self_test_types {
FM10K_TEST_MAX = FM10K_TEST_LEN FM10K_TEST_MAX = FM10K_TEST_LEN
}; };
static void fm10k_get_strings(struct net_device *dev, u32 stringset, static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data)
u8 *data)
{ {
struct fm10k_intfc *interface = netdev_priv(dev);
char *p = (char *)data; char *p = (char *)data;
int i; int i;
...@@ -135,12 +138,19 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset, ...@@ -135,12 +138,19 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) {
memcpy(p, fm10k_gstrings_stats[i].stat_string, memcpy(p, fm10k_gstrings_global_stats[i].stat_string,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
for (i = 0; i < MAX_QUEUES; i++) { if (interface->hw.mac.type != fm10k_mac_vf)
for (i = 0; i < FM10K_PF_STATS_LEN; i++) {
memcpy(p, fm10k_gstrings_pf_stats[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
for (i = 0; i < interface->hw.mac.max_queues; i++) {
sprintf(p, "tx_queue_%u_packets", i); sprintf(p, "tx_queue_%u_packets", i);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
sprintf(p, "tx_queue_%u_bytes", i); sprintf(p, "tx_queue_%u_bytes", i);
...@@ -156,18 +166,28 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset, ...@@ -156,18 +166,28 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
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_hw *hw = &interface->hw;
int stats_len = FM10K_STATIC_STATS_LEN;
switch (sset) { switch (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:
return FM10K_STATS_LEN; stats_len += FM10K_QUEUE_STATS_LEN(hw->mac.max_queues);
if (hw->mac.type != fm10k_mac_vf)
stats_len += FM10K_PF_STATS_LEN;
return stats_len;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
static void fm10k_get_ethtool_stats(struct net_device *netdev, static void fm10k_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data) struct ethtool_stats __always_unused *stats,
u64 *data)
{ {
const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64); 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);
...@@ -184,12 +204,21 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, ...@@ -184,12 +204,21 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
} }
for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) {
p = (char *)interface + fm10k_gstrings_stats[i].stat_offset; p = (char *)interface +
*(data++) = (fm10k_gstrings_stats[i].sizeof_stat == fm10k_gstrings_global_stats[i].stat_offset;
*(data++) = (fm10k_gstrings_global_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
if (interface->hw.mac.type != fm10k_mac_vf)
for (i = 0; i < FM10K_PF_STATS_LEN; i++) {
p = (char *)interface +
fm10k_gstrings_pf_stats[i].stat_offset;
*(data++) = (fm10k_gstrings_pf_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p; sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
} }
for (i = 0; i < MAX_QUEUES; i++) { for (i = 0; i < interface->hw.mac.max_queues; i++) {
struct fm10k_ring *ring; struct fm10k_ring *ring;
u64 *queue_stat; u64 *queue_stat;
...@@ -369,7 +398,7 @@ static void fm10k_get_drvinfo(struct net_device *dev, ...@@ -369,7 +398,7 @@ static void fm10k_get_drvinfo(struct net_device *dev,
strncpy(info->bus_info, pci_name(interface->pdev), strncpy(info->bus_info, pci_name(interface->pdev),
sizeof(info->bus_info) - 1); sizeof(info->bus_info) - 1);
info->n_stats = FM10K_STATS_LEN; info->n_stats = fm10k_get_sset_count(dev, ETH_SS_STATS);
info->regdump_len = fm10k_get_regs_len(dev); info->regdump_len = fm10k_get_regs_len(dev);
} }
...@@ -645,7 +674,7 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface, ...@@ -645,7 +674,7 @@ static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface,
} }
static int fm10k_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, static int fm10k_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
u32 *rule_locs) u32 __always_unused *rule_locs)
{ {
struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_intfc *interface = netdev_priv(dev);
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
...@@ -851,7 +880,7 @@ static void fm10k_self_test(struct net_device *dev, ...@@ -851,7 +880,7 @@ static void fm10k_self_test(struct net_device *dev,
eth_test->flags |= ETH_TEST_FL_FAILED; eth_test->flags |= ETH_TEST_FL_FAILED;
} }
static u32 fm10k_get_reta_size(struct net_device *netdev) static u32 fm10k_get_reta_size(struct net_device __always_unused *netdev)
{ {
return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG; return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
} }
...@@ -911,7 +940,7 @@ static int fm10k_set_reta(struct net_device *netdev, const u32 *indir) ...@@ -911,7 +940,7 @@ static int fm10k_set_reta(struct net_device *netdev, const u32 *indir)
return 0; return 0;
} }
static u32 fm10k_get_rssrk_size(struct net_device *netdev) static u32 fm10k_get_rssrk_size(struct net_device __always_unused *netdev)
{ {
return FM10K_RSSRK_SIZE * FM10K_RSSRK_ENTRIES_PER_REG; return FM10K_RSSRK_SIZE * FM10K_RSSRK_ENTRIES_PER_REG;
} }
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -47,7 +47,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface) ...@@ -47,7 +47,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface)
{ {
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
struct fm10k_iov_data *iov_data; struct fm10k_iov_data *iov_data;
s64 mbicr, vflre; s64 vflre;
int i; int i;
/* if there is no iov_data then there is no mailboxes to process */ /* if there is no iov_data then there is no mailboxes to process */
...@@ -63,7 +63,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface) ...@@ -63,7 +63,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface)
goto read_unlock; goto read_unlock;
if (!(fm10k_read_reg(hw, FM10K_EICR) & FM10K_EICR_VFLR)) if (!(fm10k_read_reg(hw, FM10K_EICR) & FM10K_EICR_VFLR))
goto process_mbx; goto read_unlock;
/* read VFLRE to determine if any VFs have been reset */ /* read VFLRE to determine if any VFs have been reset */
do { do {
...@@ -86,32 +86,6 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface) ...@@ -86,32 +86,6 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface)
} }
} while (i != iov_data->num_vfs); } while (i != iov_data->num_vfs);
process_mbx:
/* read MBICR to determine which VFs require attention */
mbicr = fm10k_read_reg(hw, FM10K_MBICR(1));
mbicr <<= 32;
mbicr |= fm10k_read_reg(hw, FM10K_MBICR(0));
i = iov_data->next_vf_mbx ? : iov_data->num_vfs;
for (mbicr <<= 64 - i; i--; mbicr += mbicr) {
struct fm10k_mbx_info *mbx = &iov_data->vf_info[i].mbx;
if (mbicr >= 0)
continue;
if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU))
break;
mbx->ops.process(hw, mbx);
}
if (i >= 0) {
iov_data->next_vf_mbx = i + 1;
} else if (iov_data->next_vf_mbx) {
iov_data->next_vf_mbx = 0;
goto process_mbx;
}
read_unlock: read_unlock:
rcu_read_unlock(); rcu_read_unlock();
...@@ -139,6 +113,13 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface) ...@@ -139,6 +113,13 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
/* lock the mailbox for transmit and receive */ /* lock the mailbox for transmit and receive */
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
/* Most VF messages sent to the PF cause the PF to respond by
* requesting from the SM mailbox. This means that too many VF
* messages processed at once could cause a mailbox timeout on the PF.
* To prevent this, store a pointer to the next VF mbx to process. Use
* that as the start of the loop so that we don't starve whichever VF
* got ignored on the previous run.
*/
process_mbx: process_mbx:
for (i = iov_data->next_vf_mbx ? : iov_data->num_vfs; i--;) { for (i = iov_data->next_vf_mbx ? : iov_data->num_vfs; i--;) {
struct fm10k_vf_info *vf_info = &iov_data->vf_info[i]; struct fm10k_vf_info *vf_info = &iov_data->vf_info[i];
...@@ -155,10 +136,6 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface) ...@@ -155,10 +136,6 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
mbx->ops.connect(hw, mbx); mbx->ops.connect(hw, mbx);
} }
/* no work pending, then just continue */
if (mbx->ops.tx_complete(mbx) && !mbx->ops.rx_ready(mbx))
continue;
/* guarantee we have free space in the SM mailbox */ /* guarantee we have free space in the SM mailbox */
if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU))
break; break;
...@@ -167,6 +144,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface) ...@@ -167,6 +144,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
mbx->ops.process(hw, mbx); mbx->ops.process(hw, mbx);
} }
/* if we stopped processing mailboxes early, update next_vf_mbx.
* Otherwise, reset next_vf_mbx, and restart loop so that we process
* the remaining mailboxes we skipped at the start.
*/
if (i >= 0) { if (i >= 0) {
iov_data->next_vf_mbx = i + 1; iov_data->next_vf_mbx = i + 1;
} else if (iov_data->next_vf_mbx) { } else if (iov_data->next_vf_mbx) {
...@@ -488,8 +469,8 @@ int fm10k_ndo_set_vf_vlan(struct net_device *netdev, int vf_idx, u16 vid, ...@@ -488,8 +469,8 @@ int fm10k_ndo_set_vf_vlan(struct net_device *netdev, int vf_idx, u16 vid,
return 0; return 0;
} }
int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx, int unused, int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx,
int rate) int __always_unused unused, int rate)
{ {
struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_intfc *interface = netdev_priv(netdev);
struct fm10k_iov_data *iov_data = interface->iov_data; struct fm10k_iov_data *iov_data = interface->iov_data;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "fm10k.h" #include "fm10k.h"
#define DRV_VERSION "0.12.2-k" #define DRV_VERSION "0.15.2-k"
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[] =
...@@ -41,6 +41,9 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Switch Host Interface Driver"); ...@@ -41,6 +41,9 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Switch Host Interface Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
/* single workqueue for entire fm10k driver */
struct workqueue_struct *fm10k_workqueue = NULL;
/** /**
* fm10k_init_module - Driver Registration Routine * fm10k_init_module - Driver Registration Routine
* *
...@@ -52,6 +55,10 @@ static int __init fm10k_init_module(void) ...@@ -52,6 +55,10 @@ static int __init fm10k_init_module(void)
pr_info("%s - version %s\n", fm10k_driver_string, fm10k_driver_version); pr_info("%s - version %s\n", fm10k_driver_string, fm10k_driver_version);
pr_info("%s\n", fm10k_copyright); pr_info("%s\n", fm10k_copyright);
/* create driver workqueue */
if (!fm10k_workqueue)
fm10k_workqueue = create_workqueue("fm10k");
fm10k_dbg_init(); fm10k_dbg_init();
return fm10k_register_pci_driver(); return fm10k_register_pci_driver();
...@@ -69,6 +76,11 @@ static void __exit fm10k_exit_module(void) ...@@ -69,6 +76,11 @@ static void __exit fm10k_exit_module(void)
fm10k_unregister_pci_driver(); fm10k_unregister_pci_driver();
fm10k_dbg_exit(); fm10k_dbg_exit();
/* destroy driver workqueue */
flush_workqueue(fm10k_workqueue);
destroy_workqueue(fm10k_workqueue);
fm10k_workqueue = NULL;
} }
module_exit(fm10k_exit_module); module_exit(fm10k_exit_module);
...@@ -209,7 +221,7 @@ static inline bool fm10k_page_is_reserved(struct page *page) ...@@ -209,7 +221,7 @@ static inline bool fm10k_page_is_reserved(struct page *page)
static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer, static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer,
struct page *page, struct page *page,
unsigned int truesize) unsigned int __maybe_unused truesize)
{ {
/* avoid re-using remote pages */ /* avoid re-using remote pages */
if (unlikely(fm10k_page_is_reserved(page))) if (unlikely(fm10k_page_is_reserved(page)))
...@@ -240,7 +252,6 @@ static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer, ...@@ -240,7 +252,6 @@ static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer,
/** /**
* fm10k_add_rx_frag - Add contents of Rx buffer to sk_buff * fm10k_add_rx_frag - Add contents of Rx buffer to sk_buff
* @rx_ring: rx descriptor ring to transact packets on
* @rx_buffer: buffer containing page to add * @rx_buffer: buffer containing page to add
* @rx_desc: descriptor containing length of buffer written by hardware * @rx_desc: descriptor containing length of buffer written by hardware
* @skb: sk_buff to place the data into * @skb: sk_buff to place the data into
...@@ -253,8 +264,7 @@ static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer, ...@@ -253,8 +264,7 @@ static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer,
* The function will then update the page offset if necessary and return * The function will then update the page offset if necessary and return
* true if the buffer can be reused by the interface. * true if the buffer can be reused by the interface.
**/ **/
static bool fm10k_add_rx_frag(struct fm10k_ring *rx_ring, static bool fm10k_add_rx_frag(struct fm10k_rx_buffer *rx_buffer,
struct fm10k_rx_buffer *rx_buffer,
union fm10k_rx_desc *rx_desc, union fm10k_rx_desc *rx_desc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -330,7 +340,7 @@ static struct sk_buff *fm10k_fetch_rx_buffer(struct fm10k_ring *rx_ring, ...@@ -330,7 +340,7 @@ static struct sk_buff *fm10k_fetch_rx_buffer(struct fm10k_ring *rx_ring,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
/* pull page into skb */ /* pull page into skb */
if (fm10k_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) { if (fm10k_add_rx_frag(rx_buffer, rx_desc, skb)) {
/* hand second half of page back to the ring */ /* hand second half of page back to the ring */
fm10k_reuse_rx_page(rx_ring, rx_buffer); fm10k_reuse_rx_page(rx_ring, rx_buffer);
} else { } else {
...@@ -412,7 +422,7 @@ static void fm10k_rx_hwtstamp(struct fm10k_ring *rx_ring, ...@@ -412,7 +422,7 @@ static void fm10k_rx_hwtstamp(struct fm10k_ring *rx_ring,
} }
static void fm10k_type_trans(struct fm10k_ring *rx_ring, static void fm10k_type_trans(struct fm10k_ring *rx_ring,
union fm10k_rx_desc *rx_desc, union fm10k_rx_desc __maybe_unused *rx_desc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct net_device *dev = rx_ring->netdev; struct net_device *dev = rx_ring->netdev;
...@@ -509,8 +519,6 @@ static bool fm10k_is_non_eop(struct fm10k_ring *rx_ring, ...@@ -509,8 +519,6 @@ static bool fm10k_is_non_eop(struct fm10k_ring *rx_ring,
/** /**
* fm10k_pull_tail - fm10k specific version of skb_pull_tail * fm10k_pull_tail - fm10k specific version of skb_pull_tail
* @rx_ring: rx descriptor ring packet is being transacted on
* @rx_desc: pointer to the EOP Rx descriptor
* @skb: pointer to current skb being adjusted * @skb: pointer to current skb being adjusted
* *
* This function is an fm10k specific version of __pskb_pull_tail. The * This function is an fm10k specific version of __pskb_pull_tail. The
...@@ -520,9 +528,7 @@ static bool fm10k_is_non_eop(struct fm10k_ring *rx_ring, ...@@ -520,9 +528,7 @@ static bool fm10k_is_non_eop(struct fm10k_ring *rx_ring,
* As a result we can do things like drop a frag and maintain an accurate * As a result we can do things like drop a frag and maintain an accurate
* truesize for the skb. * truesize for the skb.
*/ */
static void fm10k_pull_tail(struct fm10k_ring *rx_ring, static void fm10k_pull_tail(struct sk_buff *skb)
union fm10k_rx_desc *rx_desc,
struct sk_buff *skb)
{ {
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
unsigned char *va; unsigned char *va;
...@@ -576,7 +582,7 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring, ...@@ -576,7 +582,7 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring,
/* place header in linear portion of buffer */ /* place header in linear portion of buffer */
if (skb_is_nonlinear(skb)) if (skb_is_nonlinear(skb))
fm10k_pull_tail(rx_ring, rx_desc, skb); fm10k_pull_tail(skb);
/* if eth_skb_pad returns an error the skb was freed */ /* if eth_skb_pad returns an error the skb was freed */
if (eth_skb_pad(skb)) if (eth_skb_pad(skb))
...@@ -1197,7 +1203,6 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface) ...@@ -1197,7 +1203,6 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface)
{ {
/* Do the reset outside of interrupt context */ /* Do the reset outside of interrupt context */
if (!test_bit(__FM10K_DOWN, &interface->state)) { if (!test_bit(__FM10K_DOWN, &interface->state)) {
netdev_err(interface->netdev, "Reset interface\n");
interface->tx_timeout_count++; interface->tx_timeout_count++;
interface->flags |= FM10K_FLAG_RESET_REQUESTED; interface->flags |= FM10K_FLAG_RESET_REQUESTED;
fm10k_service_event_schedule(interface); fm10k_service_event_schedule(interface);
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -125,6 +125,18 @@ static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo) ...@@ -125,6 +125,18 @@ static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
return len; return len;
} }
/**
* fm10k_fifo_drop_all - Drop all messages in FIFO
* @fifo: pointer to FIFO
*
* This function resets the head pointer to drop all messages in the FIFO,
* and ensure the FIFO is empty.
**/
static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
{
fifo->head = fifo->tail;
}
/** /**
* fm10k_mbx_index_len - Convert a head/tail index into a length value * fm10k_mbx_index_len - Convert a head/tail index into a length value
* @mbx: pointer to mailbox * @mbx: pointer to mailbox
...@@ -315,7 +327,7 @@ static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len) ...@@ -315,7 +327,7 @@ static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
} while (total_len < len); } while (total_len < len);
/* message extends out of pushed section, but fits in FIFO */ /* message extends out of pushed section, but fits in FIFO */
if ((len < total_len) && (msg_len <= mbx->rx.size)) if ((len < total_len) && (msg_len <= mbx->max_size))
return 0; return 0;
/* return length of invalid section */ /* return length of invalid section */
...@@ -326,8 +338,7 @@ static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len) ...@@ -326,8 +338,7 @@ static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
* fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
* @mbx: pointer to mailbox * @mbx: pointer to mailbox
* *
* This function will take a section of the Rx FIFO and copy it into the * This function will take a section of the Tx FIFO and copy it into the
mbx->tail--;
* mailbox memory. The offset in mbmem is based on the lower bits of the * mailbox memory. The offset in mbmem is based on the lower bits of the
* tail and len determines the length to copy. * tail and len determines the length to copy.
**/ **/
...@@ -818,7 +829,7 @@ static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) ...@@ -818,7 +829,7 @@ static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
/* write new msg header to notify recipient of change */ /* write new msg header to notify recipient of change */
fm10k_write_reg(hw, mbmem, mbx->mbx_hdr); fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
/* write mailbox to sent interrupt */ /* write mailbox to send interrupt */
if (mbx->mbx_lock) if (mbx->mbx_lock)
fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock); fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock);
...@@ -1052,8 +1063,11 @@ static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx) ...@@ -1052,8 +1063,11 @@ static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
* @mbx: pointer to mailbox * @mbx: pointer to mailbox
* @size: new value for max_size * @size: new value for max_size
* *
* This function will update the max_size value and drop any outgoing messages * This function updates the max_size value and drops any outgoing messages
* from the head of the Tx FIFO that are larger than max_size. * at the head of the Tx FIFO if they are larger than max_size. It does not
* drop all messages, as this is too difficult to parse and remove them from
* the FIFO. Instead, rely on the checking to ensure that messages larger
* than max_size aren't pushed into the memory buffer.
**/ **/
static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size) static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
{ {
...@@ -1371,9 +1385,11 @@ static void fm10k_mbx_disconnect(struct fm10k_hw *hw, ...@@ -1371,9 +1385,11 @@ static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
timeout -= FM10K_MBX_POLL_DELAY; timeout -= FM10K_MBX_POLL_DELAY;
} while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED)); } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
/* in case we didn't close just force the mailbox into shutdown */ /* in case we didn't close, just force the mailbox into shutdown and
* drop all left over messages in the FIFO.
*/
fm10k_mbx_connect_reset(mbx); fm10k_mbx_connect_reset(mbx);
fm10k_mbx_update_max_size(mbx, 0); fm10k_fifo_drop_all(&mbx->tx);
fm10k_write_reg(hw, mbx->mbmem_reg, 0); fm10k_write_reg(hw, mbx->mbmem_reg, 0);
} }
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -770,15 +770,15 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) ...@@ -770,15 +770,15 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set)
if (hw->mac.vlan_override) if (hw->mac.vlan_override)
return -EACCES; return -EACCES;
/* if default VLAN is already present do nothing */
if (vid == hw->mac.default_vid)
return -EBUSY;
/* update active_vlans bitmask */ /* update active_vlans bitmask */
set_bit(vid, interface->active_vlans); set_bit(vid, interface->active_vlans);
if (!set) if (!set)
clear_bit(vid, interface->active_vlans); clear_bit(vid, interface->active_vlans);
/* if default VLAN is already present do nothing */
if (vid == hw->mac.default_vid)
return 0;
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
/* only need to update the VLAN if not in promiscuous mode */ /* only need to update the VLAN if not in promiscuous mode */
...@@ -970,14 +970,7 @@ static void fm10k_set_rx_mode(struct net_device *dev) ...@@ -970,14 +970,7 @@ static void fm10k_set_rx_mode(struct net_device *dev)
fm10k_mbx_lock(interface); fm10k_mbx_lock(interface);
/* synchronize all of the addresses */ /* update xcast mode first, but only if it changed */
if (xcast_mode != FM10K_XCAST_MODE_PROMISC) {
__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);
}
/* if we aren't changing modes there is nothing to do */
if (interface->xcast_mode != xcast_mode) { if (interface->xcast_mode != xcast_mode) {
/* update VLAN table */ /* update VLAN table */
if (xcast_mode == FM10K_XCAST_MODE_PROMISC) if (xcast_mode == FM10K_XCAST_MODE_PROMISC)
...@@ -992,6 +985,13 @@ static void fm10k_set_rx_mode(struct net_device *dev) ...@@ -992,6 +985,13 @@ static void fm10k_set_rx_mode(struct net_device *dev)
interface->xcast_mode = xcast_mode; interface->xcast_mode = xcast_mode;
} }
/* synchronize all of the addresses */
if (xcast_mode != FM10K_XCAST_MODE_PROMISC) {
__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);
}
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
} }
...@@ -1051,6 +1051,9 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1051,6 +1051,9 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
vid, true, 0); vid, true, 0);
} }
/* update xcast mode before syncronizing addresses */
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) { 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);
...@@ -1058,9 +1061,6 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) ...@@ -1058,9 +1061,6 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface)
__dev_mc_sync(netdev, fm10k_mc_sync, fm10k_mc_unsync); __dev_mc_sync(netdev, fm10k_mc_sync, fm10k_mc_unsync);
} }
/* update xcast mode */
hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode);
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
/* record updated xcast mode state */ /* record updated xcast mode state */
...@@ -1126,7 +1126,7 @@ static struct rtnl_link_stats64 *fm10k_get_stats64(struct net_device *netdev, ...@@ -1126,7 +1126,7 @@ static struct rtnl_link_stats64 *fm10k_get_stats64(struct net_device *netdev,
} }
for (i = 0; i < interface->num_tx_queues; i++) { for (i = 0; i < interface->num_tx_queues; i++) {
ring = ACCESS_ONCE(interface->rx_ring[i]); ring = ACCESS_ONCE(interface->tx_ring[i]);
if (!ring) if (!ring)
continue; continue;
...@@ -1382,6 +1382,9 @@ static const struct net_device_ops fm10k_netdev_ops = { ...@@ -1382,6 +1382,9 @@ static const struct net_device_ops fm10k_netdev_ops = {
.ndo_do_ioctl = fm10k_ioctl, .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
.ndo_poll_controller = fm10k_netpoll,
#endif
.ndo_features_check = fm10k_features_check, .ndo_features_check = fm10k_features_check,
}; };
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -94,7 +94,7 @@ void fm10k_service_event_schedule(struct fm10k_intfc *interface) ...@@ -94,7 +94,7 @@ void fm10k_service_event_schedule(struct fm10k_intfc *interface)
{ {
if (!test_bit(__FM10K_SERVICE_DISABLE, &interface->state) && if (!test_bit(__FM10K_SERVICE_DISABLE, &interface->state) &&
!test_and_set_bit(__FM10K_SERVICE_SCHED, &interface->state)) !test_and_set_bit(__FM10K_SERVICE_SCHED, &interface->state))
schedule_work(&interface->service_task); queue_work(fm10k_workqueue, &interface->service_task);
} }
static void fm10k_service_event_complete(struct fm10k_intfc *interface) static void fm10k_service_event_complete(struct fm10k_intfc *interface)
...@@ -191,7 +191,6 @@ static void fm10k_reset_subtask(struct fm10k_intfc *interface) ...@@ -191,7 +191,6 @@ static void fm10k_reset_subtask(struct fm10k_intfc *interface)
interface->flags &= ~FM10K_FLAG_RESET_REQUESTED; interface->flags &= ~FM10K_FLAG_RESET_REQUESTED;
netdev_err(interface->netdev, "Reset interface\n"); netdev_err(interface->netdev, "Reset interface\n");
interface->tx_timeout_count++;
fm10k_reinit(interface); fm10k_reinit(interface);
} }
...@@ -357,11 +356,10 @@ void fm10k_update_stats(struct fm10k_intfc *interface) ...@@ -357,11 +356,10 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
net_stats->rx_packets = pkts; net_stats->rx_packets = pkts;
interface->alloc_failed = alloc_failed; interface->alloc_failed = alloc_failed;
interface->rx_csum_errors = rx_csum_errors; interface->rx_csum_errors = rx_csum_errors;
interface->rx_errors = rx_errors;
hw->mac.ops.update_hw_stats(hw, &interface->stats); hw->mac.ops.update_hw_stats(hw, &interface->stats);
for (i = 0; i < FM10K_MAX_QUEUES_PF; i++) { for (i = 0; i < hw->mac.max_queues; i++) {
struct fm10k_hw_stats_q *q = &interface->stats.q[i]; struct fm10k_hw_stats_q *q = &interface->stats.q[i];
tx_bytes_nic += q->tx_bytes.count; tx_bytes_nic += q->tx_bytes.count;
...@@ -378,7 +376,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface) ...@@ -378,7 +376,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
interface->rx_drops_nic = rx_drops_nic; interface->rx_drops_nic = rx_drops_nic;
/* Fill out the OS statistics structure */ /* Fill out the OS statistics structure */
net_stats->rx_errors = interface->stats.xec.count; net_stats->rx_errors = rx_errors;
net_stats->rx_dropped = interface->stats.nodesc_drop.count; net_stats->rx_dropped = interface->stats.nodesc_drop.count;
} }
...@@ -808,7 +806,7 @@ static void fm10k_napi_enable_all(struct fm10k_intfc *interface) ...@@ -808,7 +806,7 @@ static void fm10k_napi_enable_all(struct fm10k_intfc *interface)
} }
} }
static irqreturn_t fm10k_msix_clean_rings(int irq, void *data) static irqreturn_t fm10k_msix_clean_rings(int __always_unused irq, void *data)
{ {
struct fm10k_q_vector *q_vector = data; struct fm10k_q_vector *q_vector = data;
...@@ -818,7 +816,7 @@ static irqreturn_t fm10k_msix_clean_rings(int irq, void *data) ...@@ -818,7 +816,7 @@ static irqreturn_t fm10k_msix_clean_rings(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t fm10k_msix_mbx_vf(int irq, void *data) static irqreturn_t fm10k_msix_mbx_vf(int __always_unused irq, void *data)
{ {
struct fm10k_intfc *interface = data; struct fm10k_intfc *interface = data;
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
...@@ -840,6 +838,28 @@ static irqreturn_t fm10k_msix_mbx_vf(int irq, void *data) ...@@ -840,6 +838,28 @@ static irqreturn_t fm10k_msix_mbx_vf(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
#ifdef CONFIG_NET_POLL_CONTROLLER
/**
* fm10k_netpoll - A Polling 'interrupt' handler
* @netdev: network interface device structure
*
* This is used by netconsole to send skbs without having to re-enable
* interrupts. It's not called while the normal interrupt routine is executing.
**/
void fm10k_netpoll(struct net_device *netdev)
{
struct fm10k_intfc *interface = netdev_priv(netdev);
int i;
/* if interface is down do nothing */
if (test_bit(__FM10K_DOWN, &interface->state))
return;
for (i = 0; i < interface->num_q_vectors; i++)
fm10k_msix_clean_rings(0, interface->q_vector[i]);
}
#endif
#define FM10K_ERR_MSG(type) case (type): error = #type; break #define FM10K_ERR_MSG(type) case (type): error = #type; break
static void fm10k_print_fault(struct fm10k_intfc *interface, int type, static void fm10k_print_fault(struct fm10k_intfc *interface, int type,
struct fm10k_fault *fault) struct fm10k_fault *fault)
...@@ -964,7 +984,7 @@ static void fm10k_reset_drop_on_empty(struct fm10k_intfc *interface, u32 eicr) ...@@ -964,7 +984,7 @@ static void fm10k_reset_drop_on_empty(struct fm10k_intfc *interface, u32 eicr)
} }
} }
static irqreturn_t fm10k_msix_mbx_pf(int irq, void *data) static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data)
{ {
struct fm10k_intfc *interface = data; struct fm10k_intfc *interface = data;
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
...@@ -986,6 +1006,7 @@ static irqreturn_t fm10k_msix_mbx_pf(int irq, void *data) ...@@ -986,6 +1006,7 @@ static irqreturn_t fm10k_msix_mbx_pf(int irq, void *data)
/* service mailboxes */ /* service mailboxes */
if (fm10k_mbx_trylock(interface)) { if (fm10k_mbx_trylock(interface)) {
mbx->ops.process(hw, mbx); mbx->ops.process(hw, mbx);
/* handle VFLRE events */
fm10k_iov_event(interface); fm10k_iov_event(interface);
fm10k_mbx_unlock(interface); fm10k_mbx_unlock(interface);
} }
...@@ -1002,6 +1023,8 @@ static irqreturn_t fm10k_msix_mbx_pf(int irq, void *data) ...@@ -1002,6 +1023,8 @@ static irqreturn_t fm10k_msix_mbx_pf(int irq, void *data)
/* we should validate host state after interrupt event */ /* we should validate host state after interrupt event */
hw->mac.get_host_state = 1; hw->mac.get_host_state = 1;
/* validate host state, and handle VF mailboxes in the service task */
fm10k_service_event_schedule(interface); fm10k_service_event_schedule(interface);
/* re-enable mailbox interrupt and indicate 20us delay */ /* re-enable mailbox interrupt and indicate 20us delay */
...@@ -1069,7 +1092,7 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results, ...@@ -1069,7 +1092,7 @@ static s32 fm10k_mbx_mac_addr(struct fm10k_hw *hw, u32 **results,
} }
static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results, static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info *mbx) struct fm10k_mbx_info __always_unused *mbx)
{ {
struct fm10k_intfc *interface; struct fm10k_intfc *interface;
u64 timestamp; u64 timestamp;
...@@ -1089,7 +1112,7 @@ static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results, ...@@ -1089,7 +1112,7 @@ static s32 fm10k_1588_msg_vf(struct fm10k_hw *hw, u32 **results,
/* 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 *mbx) struct fm10k_mbx_info __always_unused *mbx)
{ {
struct fm10k_intfc *interface; struct fm10k_intfc *interface;
struct pci_dev *pdev; struct pci_dev *pdev;
...@@ -1165,7 +1188,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results, ...@@ -1165,7 +1188,7 @@ static s32 fm10k_lport_map(struct fm10k_hw *hw, u32 **results,
} }
static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results, static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info *mbx) struct fm10k_mbx_info __always_unused *mbx)
{ {
struct fm10k_intfc *interface; struct fm10k_intfc *interface;
u16 glort, pvid; u16 glort, pvid;
...@@ -1206,7 +1229,7 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results, ...@@ -1206,7 +1229,7 @@ static s32 fm10k_update_pvid(struct fm10k_hw *hw, u32 **results,
} }
static s32 fm10k_1588_msg_pf(struct fm10k_hw *hw, u32 **results, static s32 fm10k_1588_msg_pf(struct fm10k_hw *hw, u32 **results,
struct fm10k_mbx_info *mbx) struct fm10k_mbx_info __always_unused *mbx)
{ {
struct fm10k_swapi_1588_timestamp timestamp; struct fm10k_swapi_1588_timestamp timestamp;
struct fm10k_iov_data *iov_data; struct fm10k_iov_data *iov_data;
...@@ -1488,7 +1511,7 @@ void fm10k_up(struct fm10k_intfc *interface) ...@@ -1488,7 +1511,7 @@ void fm10k_up(struct fm10k_intfc *interface)
/* enable transmits */ /* enable transmits */
netif_tx_start_all_queues(interface->netdev); netif_tx_start_all_queues(interface->netdev);
/* kick off the service timer */ /* kick off the service timer now */
hw->mac.get_host_state = 1; hw->mac.get_host_state = 1;
mod_timer(&interface->service_timer, jiffies); mod_timer(&interface->service_timer, jiffies);
} }
...@@ -1528,8 +1551,6 @@ void fm10k_down(struct fm10k_intfc *interface) ...@@ -1528,8 +1551,6 @@ void fm10k_down(struct fm10k_intfc *interface)
/* disable polling routines */ /* disable polling routines */
fm10k_napi_disable_all(interface); fm10k_napi_disable_all(interface);
del_timer_sync(&interface->service_timer);
/* capture stats one last time before stopping interface */ /* capture stats one last time before stopping interface */
fm10k_update_stats(interface); fm10k_update_stats(interface);
...@@ -1655,6 +1676,9 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, ...@@ -1655,6 +1676,9 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
(unsigned long)interface); (unsigned long)interface);
INIT_WORK(&interface->service_task, fm10k_service_task); INIT_WORK(&interface->service_task, fm10k_service_task);
/* kick off service timer now, even when interface is down */
mod_timer(&interface->service_timer, (HZ * 2) + jiffies);
/* Intitialize timestamp data */ /* Intitialize timestamp data */
fm10k_ts_init(interface); fm10k_ts_init(interface);
...@@ -1871,6 +1895,8 @@ static void fm10k_remove(struct pci_dev *pdev) ...@@ -1871,6 +1895,8 @@ static void fm10k_remove(struct pci_dev *pdev)
struct fm10k_intfc *interface = pci_get_drvdata(pdev); struct fm10k_intfc *interface = pci_get_drvdata(pdev);
struct net_device *netdev = interface->netdev; struct net_device *netdev = interface->netdev;
del_timer_sync(&interface->service_timer);
set_bit(__FM10K_SERVICE_DISABLE, &interface->state); set_bit(__FM10K_SERVICE_DISABLE, &interface->state);
cancel_work_sync(&interface->service_task); cancel_work_sync(&interface->service_task);
...@@ -1984,7 +2010,8 @@ static int fm10k_resume(struct pci_dev *pdev) ...@@ -1984,7 +2010,8 @@ static int fm10k_resume(struct pci_dev *pdev)
* a sleep state. The fm10k hardware does not support wake on lan so the * a sleep state. The fm10k hardware does not support wake on lan so the
* driver simply needs to shut down the device so it is in a low power state. * driver simply needs to shut down the device so it is in a low power state.
**/ **/
static int fm10k_suspend(struct pci_dev *pdev, pm_message_t state) static int fm10k_suspend(struct pci_dev *pdev,
pm_message_t __always_unused state)
{ {
struct fm10k_intfc *interface = pci_get_drvdata(pdev); struct fm10k_intfc *interface = pci_get_drvdata(pdev);
struct net_device *netdev = interface->netdev; struct net_device *netdev = interface->netdev;
......
...@@ -329,6 +329,9 @@ static s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort, ...@@ -329,6 +329,9 @@ static s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort,
struct fm10k_mac_update mac_update; struct fm10k_mac_update mac_update;
u32 msg[5]; u32 msg[5];
/* clear set bit from VLAN ID */
vid &= ~FM10K_VLAN_CLEAR;
/* if glort or vlan are not valid return error */ /* if glort or vlan are not valid return error */
if (!fm10k_glort_valid_pf(hw, glort) || vid >= FM10K_VLAN_TABLE_VID_MAX) if (!fm10k_glort_valid_pf(hw, glort) || vid >= FM10K_VLAN_TABLE_VID_MAX)
return FM10K_ERR_PARAM; return FM10K_ERR_PARAM;
...@@ -676,7 +679,8 @@ static s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs, ...@@ -676,7 +679,8 @@ static s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs,
/* loop through unallocated rings assigning them back to PF */ /* loop through unallocated rings assigning them back to PF */
for (i = FM10K_MAX_QUEUES_PF; i < vf_q_idx; i++) { for (i = FM10K_MAX_QUEUES_PF; i < vf_q_idx; i++) {
fm10k_write_reg(hw, FM10K_TXDCTL(i), 0); fm10k_write_reg(hw, FM10K_TXDCTL(i), 0);
fm10k_write_reg(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF | vid); fm10k_write_reg(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF |
FM10K_TXQCTL_UNLIMITED_BW | vid);
fm10k_write_reg(hw, FM10K_RXQCTL(i), FM10K_RXQCTL_PF); fm10k_write_reg(hw, FM10K_RXQCTL(i), FM10K_RXQCTL_PF);
} }
...@@ -1249,8 +1253,8 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, ...@@ -1249,8 +1253,8 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
} }
/* notify switch of request for new multicast address */ /* notify switch of request for new multicast address */
err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, vlan,
!(vlan & FM10K_VLAN_CLEAR), 0); !(vlan & FM10K_VLAN_CLEAR));
} }
return err; return err;
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -319,7 +319,8 @@ static int fm10k_ptp_settime(struct ptp_clock_info *ptp, ...@@ -319,7 +319,8 @@ static int fm10k_ptp_settime(struct ptp_clock_info *ptp,
} }
static int fm10k_ptp_enable(struct ptp_clock_info *ptp, static int fm10k_ptp_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on) struct ptp_clock_request *rq,
int __always_unused on)
{ {
struct ptp_clock_time *t = &rq->perout.period; struct ptp_clock_time *t = &rq->perout.period;
struct fm10k_intfc *interface; struct fm10k_intfc *interface;
......
/* Intel Ethernet Switch Host Interface Driver /* Intel Ethernet Switch Host Interface Driver
* Copyright(c) 2013 - 2014 Intel Corporation. * Copyright(c) 2013 - 2015 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,
...@@ -124,6 +124,10 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) ...@@ -124,6 +124,10 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw)
/* record maximum queue count */ /* record maximum queue count */
hw->mac.max_queues = i; hw->mac.max_queues = i;
/* fetch default VLAN */
hw->mac.default_vid = (fm10k_read_reg(hw, FM10K_TXQCTL(0)) &
FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT;
return 0; return 0;
} }
......
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