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

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
* 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
* under the terms and conditions of the GNU General Public License,
......@@ -235,6 +235,9 @@ struct fm10k_vxlan_port {
__be16 port;
};
/* one work queue for entire driver */
extern struct workqueue_struct *fm10k_workqueue;
struct fm10k_intfc {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct net_device *netdev;
......@@ -266,7 +269,6 @@ struct fm10k_intfc {
u64 tx_csum_errors;
u64 alloc_failed;
u64 rx_csum_errors;
u64 rx_errors;
u64 tx_bytes_nic;
u64 tx_packets_nic;
......@@ -458,6 +460,9 @@ void fm10k_down(struct fm10k_intfc *interface);
void fm10k_update_stats(struct fm10k_intfc *interface);
void fm10k_service_event_schedule(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 */
struct net_device *fm10k_alloc_netdev(void);
......
/* 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
* 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)
*
* 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;
}
......@@ -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
**/
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;
}
......
/* 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
* 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)
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;
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. */
}
......
/* 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
* under the terms and conditions of the GNU General Public License,
......@@ -57,13 +57,12 @@ static const struct fm10k_stats fm10k_gstrings_net_stats[] = {
.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_busy", tx_busy),
FM10K_STAT("tx_csum_errors", tx_csum_errors),
FM10K_STAT("rx_alloc_failed", alloc_failed),
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_bytes_nic", tx_bytes_nic),
......@@ -73,38 +72,42 @@ static const struct fm10k_stats fm10k_gstrings_stats[] = {
FM10K_STAT("rx_overrun_pf", rx_overrun_pf),
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("mac_rules_used", hw.swapi.mac.used),
FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail),
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_dwords", hw.mbx.tx_dwords),
FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages),
FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords),
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),
};
#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 \
(MAX_QUEUES * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64)))
#define FM10K_QUEUE_STATS_LEN(_n) \
( (_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64)))
#define FM10K_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \
FM10K_NETDEV_STATS_LEN + \
FM10K_QUEUE_STATS_LEN)
#define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \
FM10K_NETDEV_STATS_LEN)
static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = {
"Mailbox test (on/offline)"
......@@ -117,9 +120,9 @@ enum fm10k_self_test_types {
FM10K_TEST_MAX = FM10K_TEST_LEN
};
static void fm10k_get_strings(struct net_device *dev, u32 stringset,
u8 *data)
static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
struct fm10k_intfc *interface = netdev_priv(dev);
char *p = (char *)data;
int i;
......@@ -135,12 +138,19 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset,
p += ETH_GSTRING_LEN;
}
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);
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);
p += ETH_GSTRING_LEN;
sprintf(p, "tx_queue_%u_bytes", i);
......@@ -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)
{
struct fm10k_intfc *interface = netdev_priv(dev);
struct fm10k_hw *hw = &interface->hw;
int stats_len = FM10K_STATIC_STATS_LEN;
switch (sset) {
case ETH_SS_TEST:
return FM10K_TEST_LEN;
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:
return -EOPNOTSUPP;
}
}
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);
struct fm10k_intfc *interface = netdev_priv(netdev);
......@@ -184,12 +204,21 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev,
}
for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) {
p = (char *)interface + fm10k_gstrings_stats[i].stat_offset;
*(data++) = (fm10k_gstrings_stats[i].sizeof_stat ==
p = (char *)interface +
fm10k_gstrings_global_stats[i].stat_offset;
*(data++) = (fm10k_gstrings_global_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
for (i = 0; i < MAX_QUEUES; i++) {
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;
}
for (i = 0; i < interface->hw.mac.max_queues; i++) {
struct fm10k_ring *ring;
u64 *queue_stat;
......@@ -369,7 +398,7 @@ static void fm10k_get_drvinfo(struct net_device *dev,
strncpy(info->bus_info, pci_name(interface->pdev),
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);
}
......@@ -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,
u32 *rule_locs)
u32 __always_unused *rule_locs)
{
struct fm10k_intfc *interface = netdev_priv(dev);
int ret = -EOPNOTSUPP;
......@@ -851,7 +880,7 @@ static void fm10k_self_test(struct net_device *dev,
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;
}
......@@ -911,7 +940,7 @@ static int fm10k_set_reta(struct net_device *netdev, const u32 *indir)
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;
}
......
/* 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
* under the terms and conditions of the GNU General Public License,
......@@ -47,7 +47,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface)
{
struct fm10k_hw *hw = &interface->hw;
struct fm10k_iov_data *iov_data;
s64 mbicr, vflre;
s64 vflre;
int i;
/* 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)
goto read_unlock;
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 */
do {
......@@ -86,32 +86,6 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface)
}
} 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:
rcu_read_unlock();
......@@ -139,6 +113,13 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
/* lock the mailbox for transmit and receive */
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:
for (i = iov_data->next_vf_mbx ? : iov_data->num_vfs; i--;) {
struct fm10k_vf_info *vf_info = &iov_data->vf_info[i];
......@@ -155,10 +136,6 @@ process_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 */
if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU))
break;
......@@ -167,6 +144,10 @@ process_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) {
iov_data->next_vf_mbx = i + 1;
} 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,
return 0;
}
int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx, int unused,
int rate)
int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx,
int __always_unused unused, int rate)
{
struct fm10k_intfc *interface = netdev_priv(netdev);
struct fm10k_iov_data *iov_data = interface->iov_data;
......
......@@ -28,7 +28,7 @@
#include "fm10k.h"
#define DRV_VERSION "0.12.2-k"
#define DRV_VERSION "0.15.2-k"
const char fm10k_driver_version[] = DRV_VERSION;
char fm10k_driver_name[] = "fm10k";
static const char fm10k_driver_string[] =
......@@ -41,6 +41,9 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Switch Host Interface Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
/* single workqueue for entire fm10k driver */
struct workqueue_struct *fm10k_workqueue = NULL;
/**
* fm10k_init_module - Driver Registration Routine
*
......@@ -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\n", fm10k_copyright);
/* create driver workqueue */
if (!fm10k_workqueue)
fm10k_workqueue = create_workqueue("fm10k");
fm10k_dbg_init();
return fm10k_register_pci_driver();
......@@ -69,6 +76,11 @@ static void __exit fm10k_exit_module(void)
fm10k_unregister_pci_driver();
fm10k_dbg_exit();
/* destroy driver workqueue */
flush_workqueue(fm10k_workqueue);
destroy_workqueue(fm10k_workqueue);
fm10k_workqueue = NULL;
}
module_exit(fm10k_exit_module);
......@@ -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,
struct page *page,
unsigned int truesize)
unsigned int __maybe_unused truesize)
{
/* avoid re-using remote pages */
if (unlikely(fm10k_page_is_reserved(page)))
......@@ -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
* @rx_ring: rx descriptor ring to transact packets on
* @rx_buffer: buffer containing page to add
* @rx_desc: descriptor containing length of buffer written by hardware
* @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,
* The function will then update the page offset if necessary and return
* true if the buffer can be reused by the interface.
**/
static bool fm10k_add_rx_frag(struct fm10k_ring *rx_ring,
struct fm10k_rx_buffer *rx_buffer,
static bool fm10k_add_rx_frag(struct fm10k_rx_buffer *rx_buffer,
union fm10k_rx_desc *rx_desc,
struct sk_buff *skb)
{
......@@ -330,7 +340,7 @@ static struct sk_buff *fm10k_fetch_rx_buffer(struct fm10k_ring *rx_ring,
DMA_FROM_DEVICE);
/* 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 */
fm10k_reuse_rx_page(rx_ring, rx_buffer);
} else {
......@@ -412,7 +422,7 @@ static void fm10k_rx_hwtstamp(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 net_device *dev = rx_ring->netdev;
......@@ -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
* @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
*
* 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,
* As a result we can do things like drop a frag and maintain an accurate
* truesize for the skb.
*/
static void fm10k_pull_tail(struct fm10k_ring *rx_ring,
union fm10k_rx_desc *rx_desc,
struct sk_buff *skb)
static void fm10k_pull_tail(struct sk_buff *skb)
{
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
unsigned char *va;
......@@ -576,7 +582,7 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring,
/* place header in linear portion of buffer */
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(skb))
......@@ -1197,7 +1203,6 @@ void fm10k_tx_timeout_reset(struct fm10k_intfc *interface)
{
/* Do the reset outside of interrupt context */
if (!test_bit(__FM10K_DOWN, &interface->state)) {
netdev_err(interface->netdev, "Reset interface\n");
interface->tx_timeout_count++;
interface->flags |= FM10K_FLAG_RESET_REQUESTED;
fm10k_service_event_schedule(interface);
......
/* 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
* 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)
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
* @mbx: pointer to mailbox
......@@ -315,7 +327,7 @@ static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
} while (total_len < len);
/* 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 length of invalid section */
......@@ -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
* @mbx: pointer to mailbox
*
* This function will take a section of the Rx FIFO and copy it into the
mbx->tail--;
* This function will take a section of the Tx FIFO and copy it into the
* mailbox memory. The offset in mbmem is based on the lower bits of the
* 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)
/* write new msg header to notify recipient of change */
fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
/* write mailbox to sent interrupt */
/* write mailbox to send interrupt */
if (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)
* @mbx: pointer to mailbox
* @size: new value for max_size
*
* This function will update the max_size value and drop any outgoing messages
* from the head of the Tx FIFO that are larger than max_size.
* This function updates the max_size value and drops any outgoing messages
* 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)
{
......@@ -1371,9 +1385,11 @@ static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
timeout -= FM10K_MBX_POLL_DELAY;
} 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_update_max_size(mbx, 0);
fm10k_fifo_drop_all(&mbx->tx);
fm10k_write_reg(hw, mbx->mbmem_reg, 0);
}
......
/* 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
* 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)
if (hw->mac.vlan_override)
return -EACCES;
/* if default VLAN is already present do nothing */
if (vid == hw->mac.default_vid)
return -EBUSY;
/* update active_vlans bitmask */