Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 15, 2015
2 parents bae97d8 + f4f88c6 commit 9f91514
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 138 deletions.
9 changes: 7 additions & 2 deletions drivers/net/ethernet/intel/fm10k/fm10k.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ethernet/intel/fm10k/fm10k_dcbnl.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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,
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
8 changes: 5 additions & 3 deletions drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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,
Expand Down Expand Up @@ -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. */
}
Expand Down
93 changes: 61 additions & 32 deletions drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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,
Expand Down Expand Up @@ -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),
Expand All @@ -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)"
Expand All @@ -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;

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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;

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
51 changes: 16 additions & 35 deletions drivers/net/ethernet/intel/fm10k/fm10k_iov.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* 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,
Expand Down Expand Up @@ -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 */
Expand All @@ -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 {
Expand All @@ -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();

Expand Down Expand Up @@ -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];
Expand All @@ -155,10 +136,6 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
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;
Expand All @@ -167,6 +144,10 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
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) {
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 9f91514

Please sign in to comment.