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/net-next

Jeff Kirsher says:

====================
This series contains updates to vxlan, net, ixgbe, ixgbevf, and i40e.

Joseph provides a single patch against vxlan which removes the burden
from the NIC drivers to check if the vxlan driver is enabled in the
kernel and also makes available the vxlan headrooms to the drivers.

Jacob provides majority of the patches, with patches against net, ixgbe
and ixgbevf.  His net patch adds might_sleep() call to napi_disable so
that every use of napi_disable during atomic context will be visible.
Then Jacob provides a patch to fix qv_lock_napi call in
ixgbe_napi_disable_all.  The other ixgbe patches cleanup
ixgbe_check_minimum_link function to correctly show that there are some
minor loss of encoding, even though we don't calculate it and remove
unnecessary duplication of PCIe bandwidth display.  Lastly, Jacob
provides 4 patches against ixgbevf to add ixgbevf_rx_skb in line with
how ixgbe handles the variations on how packets can be received, adds
support in order to track how many packets were cleaned during busy poll
as part of the extended statistics.

Wei Yongjun provides a fix for i40e to return -ENOMEN in the memory
allocation error handling case instead of returning 0, as done
elsewhere in this function.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 29, 2013
2 parents d4a0acb + ed87ac0 commit aa58d98
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 81 deletions.
4 changes: 3 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7204,8 +7204,10 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
len = sizeof(struct i40e_vsi *) * pf->hw.func_caps.num_vsis;
pf->vsi = kzalloc(len, GFP_KERNEL);
if (!pf->vsi)
if (!pf->vsi) {
err = -ENOMEM;
goto err_switch_setup;
}

err = i40e_setup_pf_switch(pf);
if (err) {
Expand Down
48 changes: 36 additions & 12 deletions drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,11 +369,13 @@ struct ixgbe_q_vector {
#ifdef CONFIG_NET_RX_BUSY_POLL
unsigned int state;
#define IXGBE_QV_STATE_IDLE 0
#define IXGBE_QV_STATE_NAPI 1 /* NAPI owns this QV */
#define IXGBE_QV_STATE_POLL 2 /* poll owns this QV */
#define IXGBE_QV_LOCKED (IXGBE_QV_STATE_NAPI | IXGBE_QV_STATE_POLL)
#define IXGBE_QV_STATE_NAPI_YIELD 4 /* NAPI yielded this QV */
#define IXGBE_QV_STATE_POLL_YIELD 8 /* poll yielded this QV */
#define IXGBE_QV_STATE_NAPI 1 /* NAPI owns this QV */
#define IXGBE_QV_STATE_POLL 2 /* poll owns this QV */
#define IXGBE_QV_STATE_DISABLED 4 /* QV is disabled */
#define IXGBE_QV_OWNED (IXGBE_QV_STATE_NAPI | IXGBE_QV_STATE_POLL)
#define IXGBE_QV_LOCKED (IXGBE_QV_OWNED | IXGBE_QV_STATE_DISABLED)
#define IXGBE_QV_STATE_NAPI_YIELD 8 /* NAPI yielded this QV */
#define IXGBE_QV_STATE_POLL_YIELD 16 /* poll yielded this QV */
#define IXGBE_QV_YIELD (IXGBE_QV_STATE_NAPI_YIELD | IXGBE_QV_STATE_POLL_YIELD)
#define IXGBE_QV_USER_PEND (IXGBE_QV_STATE_POLL | IXGBE_QV_STATE_POLL_YIELD)
spinlock_t lock;
Expand All @@ -394,7 +396,7 @@ static inline void ixgbe_qv_init_lock(struct ixgbe_q_vector *q_vector)
static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector)
{
int rc = true;
spin_lock(&q_vector->lock);
spin_lock_bh(&q_vector->lock);
if (q_vector->state & IXGBE_QV_LOCKED) {
WARN_ON(q_vector->state & IXGBE_QV_STATE_NAPI);
q_vector->state |= IXGBE_QV_STATE_NAPI_YIELD;
Expand All @@ -405,22 +407,23 @@ static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector)
} else
/* we don't care if someone yielded */
q_vector->state = IXGBE_QV_STATE_NAPI;
spin_unlock(&q_vector->lock);
spin_unlock_bh(&q_vector->lock);
return rc;
}

/* returns true is someone tried to get the qv while napi had it */
static inline bool ixgbe_qv_unlock_napi(struct ixgbe_q_vector *q_vector)
{
int rc = false;
spin_lock(&q_vector->lock);
spin_lock_bh(&q_vector->lock);
WARN_ON(q_vector->state & (IXGBE_QV_STATE_POLL |
IXGBE_QV_STATE_NAPI_YIELD));

if (q_vector->state & IXGBE_QV_STATE_POLL_YIELD)
rc = true;
q_vector->state = IXGBE_QV_STATE_IDLE;
spin_unlock(&q_vector->lock);
/* will reset state to idle, unless QV is disabled */
q_vector->state &= IXGBE_QV_STATE_DISABLED;
spin_unlock_bh(&q_vector->lock);
return rc;
}

Expand Down Expand Up @@ -451,17 +454,32 @@ static inline bool ixgbe_qv_unlock_poll(struct ixgbe_q_vector *q_vector)

if (q_vector->state & IXGBE_QV_STATE_POLL_YIELD)
rc = true;
q_vector->state = IXGBE_QV_STATE_IDLE;
/* will reset state to idle, unless QV is disabled */
q_vector->state &= IXGBE_QV_STATE_DISABLED;
spin_unlock_bh(&q_vector->lock);
return rc;
}

/* true if a socket is polling, even if it did not get the lock */
static inline bool ixgbe_qv_busy_polling(struct ixgbe_q_vector *q_vector)
{
WARN_ON(!(q_vector->state & IXGBE_QV_LOCKED));
WARN_ON(!(q_vector->state & IXGBE_QV_OWNED));
return q_vector->state & IXGBE_QV_USER_PEND;
}

/* false if QV is currently owned */
static inline bool ixgbe_qv_disable(struct ixgbe_q_vector *q_vector)
{
int rc = true;
spin_lock_bh(&q_vector->lock);
if (q_vector->state & IXGBE_QV_OWNED)
rc = false;
q_vector->state |= IXGBE_QV_STATE_DISABLED;
spin_unlock_bh(&q_vector->lock);

return rc;
}

#else /* CONFIG_NET_RX_BUSY_POLL */
static inline void ixgbe_qv_init_lock(struct ixgbe_q_vector *q_vector)
{
Expand Down Expand Up @@ -491,6 +509,12 @@ static inline bool ixgbe_qv_busy_polling(struct ixgbe_q_vector *q_vector)
{
return false;
}

static inline bool ixgbe_qv_disable(struct ixgbe_q_vector *q_vector)
{
return true;
}

#endif /* CONFIG_NET_RX_BUSY_POLL */

#ifdef CONFIG_IXGBE_HWMON
Expand Down
46 changes: 17 additions & 29 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter,
max_gts = 4 * width;
break;
case PCIE_SPEED_8_0GT:
/* 128b/130b encoding only reduces throughput by 1% */
/* 128b/130b encoding reduces throughput by less than 2% */
max_gts = 8 * width;
break;
default:
Expand All @@ -263,7 +263,7 @@ static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter,
width,
(speed == PCIE_SPEED_2_5GT ? "20%" :
speed == PCIE_SPEED_5_0GT ? "20%" :
speed == PCIE_SPEED_8_0GT ? "N/a" :
speed == PCIE_SPEED_8_0GT ? "<2%" :
"Unknown"));

if (max_gts < expected_gts) {
Expand Down Expand Up @@ -3891,15 +3891,13 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
{
int q_idx;

local_bh_disable(); /* for ixgbe_qv_lock_napi() */
for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) {
napi_disable(&adapter->q_vector[q_idx]->napi);
while (!ixgbe_qv_lock_napi(adapter->q_vector[q_idx])) {
while (!ixgbe_qv_disable(adapter->q_vector[q_idx])) {
pr_info("QV %d locked\n", q_idx);
mdelay(1);
usleep_range(1000, 20000);
}
}
local_bh_enable();
}

#ifdef CONFIG_IXGBE_DCB
Expand Down Expand Up @@ -7754,29 +7752,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ixgbe_pcie_from_parent(hw))
ixgbe_get_parent_bus_info(adapter);

/* print bus type/speed/width info */
e_dev_info("(PCI Express:%s:%s) %pM\n",
(hw->bus.speed == ixgbe_bus_speed_8000 ? "8.0GT/s" :
hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" :
hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5GT/s" :
"Unknown"),
(hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" :
hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" :
hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" :
"Unknown"),
netdev->dev_addr);

err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH);
if (err)
strncpy(part_str, "Unknown", IXGBE_PBANUM_LENGTH);
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, hw->phy.sfp_type,
part_str);
else
e_dev_info("MAC: %d, PHY: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, part_str);

/* calculate the expected PCIe bandwidth required for optimal
* performance. Note that some older parts will never have enough
* bandwidth due to being older generation PCIe parts. We clamp these
Expand All @@ -7792,6 +7767,19 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
ixgbe_check_minimum_link(adapter, expected_gts);

err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH);
if (err)
strncpy(part_str, "Unknown", IXGBE_PBANUM_LENGTH);
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, hw->phy.sfp_type,
part_str);
else
e_dev_info("MAC: %d, PHY: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, part_str);

e_dev_info("%pM\n", netdev->dev_addr);

/* reset the hardware with the new settings */
err = hw->mac.ops.start_hw(hw);
if (err == IXGBE_ERR_EEPROM_VERSION) {
Expand Down
98 changes: 71 additions & 27 deletions drivers/net/ethernet/intel/ixgbevf/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,27 @@

struct ixgbe_stats {
char stat_string[ETH_GSTRING_LEN];
int sizeof_stat;
int stat_offset;
int base_stat_offset;
int saved_reset_offset;
struct {
int sizeof_stat;
int stat_offset;
int base_stat_offset;
int saved_reset_offset;
};
};

#define IXGBEVF_STAT(m, b, r) sizeof(((struct ixgbevf_adapter *)0)->m), \
offsetof(struct ixgbevf_adapter, m), \
offsetof(struct ixgbevf_adapter, b), \
offsetof(struct ixgbevf_adapter, r)
#define IXGBEVF_STAT(m, b, r) { \
.sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, m), \
.stat_offset = offsetof(struct ixgbevf_adapter, m), \
.base_stat_offset = offsetof(struct ixgbevf_adapter, b), \
.saved_reset_offset = offsetof(struct ixgbevf_adapter, r) \
}

#define IXGBEVF_ZSTAT(m) { \
.sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, m), \
.stat_offset = offsetof(struct ixgbevf_adapter, m), \
.base_stat_offset = -1, \
.saved_reset_offset = -1 \
}

static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc,
Expand All @@ -65,15 +76,20 @@ static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
stats.saved_reset_vfgorc)},
{"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc,
stats.saved_reset_vfgotc)},
{"tx_busy", IXGBEVF_STAT(tx_busy, zero_base, zero_base)},
{"tx_busy", IXGBEVF_ZSTAT(tx_busy)},
{"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc,
stats.saved_reset_vfmprc)},
{"rx_csum_offload_good", IXGBEVF_STAT(hw_csum_rx_good, zero_base,
zero_base)},
{"rx_csum_offload_errors", IXGBEVF_STAT(hw_csum_rx_error, zero_base,
zero_base)},
{"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base,
zero_base)},
{"rx_csum_offload_good", IXGBEVF_ZSTAT(hw_csum_rx_good)},
{"rx_csum_offload_errors", IXGBEVF_ZSTAT(hw_csum_rx_error)},
{"tx_csum_offload_ctxt", IXGBEVF_ZSTAT(hw_csum_tx_good)},
#ifdef BP_EXTENDED_STATS
{"rx_bp_poll_yield", IXGBEVF_ZSTAT(bp_rx_yields)},
{"rx_bp_cleaned", IXGBEVF_ZSTAT(bp_rx_cleaned)},
{"rx_bp_misses", IXGBEVF_ZSTAT(bp_rx_missed)},
{"tx_bp_napi_yield", IXGBEVF_ZSTAT(bp_tx_yields)},
{"tx_bp_cleaned", IXGBEVF_ZSTAT(bp_tx_cleaned)},
{"tx_bp_misses", IXGBEVF_ZSTAT(bp_tx_missed)},
#endif
};

#define IXGBE_QUEUE_STATS_LEN 0
Expand Down Expand Up @@ -390,22 +406,50 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
char *base = (char *) adapter;
int i;
#ifdef BP_EXTENDED_STATS
u64 rx_yields = 0, rx_cleaned = 0, rx_missed = 0,
tx_yields = 0, tx_cleaned = 0, tx_missed = 0;

for (i = 0; i < adapter->num_rx_queues; i++) {
rx_yields += adapter->rx_ring[i].bp_yields;
rx_cleaned += adapter->rx_ring[i].bp_cleaned;
rx_yields += adapter->rx_ring[i].bp_yields;
}

for (i = 0; i < adapter->num_tx_queues; i++) {
tx_yields += adapter->tx_ring[i].bp_yields;
tx_cleaned += adapter->tx_ring[i].bp_cleaned;
tx_yields += adapter->tx_ring[i].bp_yields;
}

adapter->bp_rx_yields = rx_yields;
adapter->bp_rx_cleaned = rx_cleaned;
adapter->bp_rx_missed = rx_missed;

adapter->bp_tx_yields = tx_yields;
adapter->bp_tx_cleaned = tx_cleaned;
adapter->bp_tx_missed = tx_missed;
#endif

ixgbevf_update_stats(adapter);
for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
char *p = (char *)adapter +
ixgbe_gstrings_stats[i].stat_offset;
char *b = (char *)adapter +
ixgbe_gstrings_stats[i].base_stat_offset;
char *r = (char *)adapter +
ixgbe_gstrings_stats[i].saved_reset_offset;
data[i] = ((ixgbe_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p) -
((ixgbe_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)b : *(u32 *)b) +
((ixgbe_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)r : *(u32 *)r);
char *p = base + ixgbe_gstrings_stats[i].stat_offset;
char *b = base + ixgbe_gstrings_stats[i].base_stat_offset;
char *r = base + ixgbe_gstrings_stats[i].saved_reset_offset;

if (ixgbe_gstrings_stats[i].sizeof_stat == sizeof(u64)) {
if (ixgbe_gstrings_stats[i].base_stat_offset >= 0)
data[i] = *(u64 *)p - *(u64 *)b + *(u64 *)r;
else
data[i] = *(u64 *)p;
} else {
if (ixgbe_gstrings_stats[i].base_stat_offset >= 0)
data[i] = *(u32 *)p - *(u32 *)b + *(u32 *)r;
else
data[i] = *(u32 *)p;
}
}
}

Expand Down
Loading

0 comments on commit aa58d98

Please sign in to comment.