Skip to content

Commit

Permalink
Merge branch '100GbE' 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:

====================
100GbE Intel Wired LAN Driver Updates 2016-08-29

This series contains updates to fm10k only.

Jake provides all the changes in this series starting with fixes an issue
where VF devices may fail during an unbind/bind and we will never zero
the reference counter for the pci_dev structure.  Updated the hot path
to use SW counters instead of checking for hardware Tx pending for
possible transmit hangs, which will improve performance.  Fixed the NAPI
budget accounting so that fm10k_poll will return actual work done,
capped at (budget - 1) instead of returning 0.  Added a check to ensure
that the device is in the normal IO state before continuing to probe,
which allows us to give a more descriptive message of what is wrong
in the case of uncorrectable AER error.  In preparation for adding Geneve
Rx offload support, refactored the current VXLAN offload flow to be a bit
more generic.  Added support for receive offloads on one Geneve tunnel.
Ensure that other bits in the RXQCTL register do not get cleared, to
make sure that bits related to queue ownership are maintained.  Fixed
an issue in queue ownership assignment which casued a race condition
between the PF and the VF such that potentially a VF could cause FUM
fault errors due to normal PF/VF driver behavior.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 30, 2016
2 parents 6abdd5f + 325782a commit 3201a39
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 122 deletions.
10 changes: 4 additions & 6 deletions drivers/net/ethernet/intel/fm10k/fm10k.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,7 @@ struct fm10k_iov_data {
struct fm10k_vf_info vf_info[0];
};

#define fm10k_vxlan_port_for_each(vp, intfc) \
list_for_each_entry(vp, &(intfc)->vxlan_port, list)
struct fm10k_vxlan_port {
struct fm10k_udp_port {
struct list_head list;
sa_family_t sa_family;
__be16 port;
Expand Down Expand Up @@ -335,8 +333,9 @@ struct fm10k_intfc {
u32 reta[FM10K_RETA_SIZE];
u32 rssrk[FM10K_RSSRK_SIZE];

/* VXLAN port tracking information */
/* UDP encapsulation port tracking information */
struct list_head vxlan_port;
struct list_head geneve_port;

#ifdef CONFIG_DEBUG_FS
struct dentry *dbg_intfc;
Expand Down Expand Up @@ -458,7 +457,7 @@ __be16 fm10k_tx_encap_offload(struct sk_buff *skb);
netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
struct fm10k_ring *tx_ring);
void fm10k_tx_timeout_reset(struct fm10k_intfc *interface);
u64 fm10k_get_tx_pending(struct fm10k_ring *ring);
u64 fm10k_get_tx_pending(struct fm10k_ring *ring, bool in_sw);
bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring);
void fm10k_alloc_rx_buffers(struct fm10k_ring *rx_ring, u16 cleaned_count);

Expand Down Expand Up @@ -496,7 +495,6 @@ int fm10k_close(struct net_device *netdev);

/* Ethtool */
void fm10k_set_ethtool_ops(struct net_device *dev);
u32 fm10k_get_reta_size(struct net_device *netdev);
void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir);

/* IOV */
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/intel/fm10k/fm10k_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ s32 fm10k_disable_queues_generic(struct fm10k_hw *hw, u16 q_cnt)
/* clear tx_ready to prevent any false hits for reset */
hw->mac.tx_ready = false;

if (FM10K_REMOVED(hw->hw_addr))
return 0;

/* clear the enable bit for all rings */
for (i = 0; i < q_cnt; i++) {
reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/intel/fm10k/fm10k_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ u32 fm10k_read_reg(struct fm10k_hw *hw, int reg);
/* write operations, indexed using DWORDS */
#define fm10k_write_reg(hw, reg, val) \
do { \
u32 __iomem *hw_addr = ACCESS_ONCE((hw)->hw_addr); \
u32 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \
if (!FM10K_REMOVED(hw_addr)) \
writel((val), &hw_addr[(reg)]); \
} while (0)

/* Switch register write operations, index using DWORDS */
#define fm10k_write_sw_reg(hw, reg, val) \
do { \
u32 __iomem *sw_addr = ACCESS_ONCE((hw)->sw_addr); \
u32 __iomem *sw_addr = READ_ONCE((hw)->sw_addr); \
if (!FM10K_REMOVED(sw_addr)) \
writel((val), &sw_addr[(reg)]); \
} while (0)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags)
return 0;
}

u32 fm10k_get_reta_size(struct net_device __always_unused *netdev)
static u32 fm10k_get_reta_size(struct net_device __always_unused *netdev)
{
return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/intel/fm10k/fm10k_iov.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ s32 fm10k_iov_event(struct fm10k_intfc *interface)
int i;

/* if there is no iov_data then there is no mailbox to process */
if (!ACCESS_ONCE(interface->iov_data))
if (!READ_ONCE(interface->iov_data))
return 0;

rcu_read_lock();
Expand Down Expand Up @@ -99,7 +99,7 @@ s32 fm10k_iov_mbx(struct fm10k_intfc *interface)
int i;

/* if there is no iov_data then there is no mailbox to process */
if (!ACCESS_ONCE(interface->iov_data))
if (!READ_ONCE(interface->iov_data))
return 0;

rcu_read_lock();
Expand Down
29 changes: 20 additions & 9 deletions drivers/net/ethernet/intel/fm10k/fm10k_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static int __init fm10k_init_module(void)
pr_info("%s\n", fm10k_copyright);

/* create driver workqueue */
fm10k_workqueue = alloc_workqueue("fm10k", WQ_MEM_RECLAIM, 0);
fm10k_workqueue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, fm10k_driver_name);

fm10k_dbg_init();

Expand Down Expand Up @@ -651,11 +651,11 @@ static int fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
static struct ethhdr *fm10k_port_is_vxlan(struct sk_buff *skb)
{
struct fm10k_intfc *interface = netdev_priv(skb->dev);
struct fm10k_vxlan_port *vxlan_port;
struct fm10k_udp_port *vxlan_port;

/* we can only offload a vxlan if we recognize it as such */
vxlan_port = list_first_entry_or_null(&interface->vxlan_port,
struct fm10k_vxlan_port, list);
struct fm10k_udp_port, list);

if (!vxlan_port)
return NULL;
Expand Down Expand Up @@ -1128,13 +1128,24 @@ static u64 fm10k_get_tx_completed(struct fm10k_ring *ring)
return ring->stats.packets;
}

u64 fm10k_get_tx_pending(struct fm10k_ring *ring)
/**
* fm10k_get_tx_pending - how many Tx descriptors not processed
* @ring: the ring structure
* @in_sw: is tx_pending being checked in SW or in HW?
*/
u64 fm10k_get_tx_pending(struct fm10k_ring *ring, bool in_sw)
{
struct fm10k_intfc *interface = ring->q_vector->interface;
struct fm10k_hw *hw = &interface->hw;
u32 head, tail;

u32 head = fm10k_read_reg(hw, FM10K_TDH(ring->reg_idx));
u32 tail = fm10k_read_reg(hw, FM10K_TDT(ring->reg_idx));
if (likely(in_sw)) {
head = ring->next_to_clean;
tail = ring->next_to_use;
} else {
head = fm10k_read_reg(hw, FM10K_TDH(ring->reg_idx));
tail = fm10k_read_reg(hw, FM10K_TDT(ring->reg_idx));
}

return ((head <= tail) ? tail : tail + ring->count) - head;
}
Expand All @@ -1143,7 +1154,7 @@ bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring)
{
u32 tx_done = fm10k_get_tx_completed(tx_ring);
u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
u32 tx_pending = fm10k_get_tx_pending(tx_ring);
u32 tx_pending = fm10k_get_tx_pending(tx_ring, true);

clear_check_for_tx_hang(tx_ring);

Expand Down Expand Up @@ -1397,7 +1408,7 @@ static void fm10k_update_itr(struct fm10k_ring_container *ring_container)
* that the calculation will never get below a 1. The bit shift
* accounts for changes in the ITR due to PCIe link speed.
*/
itr_round = ACCESS_ONCE(ring_container->itr_scale) + 8;
itr_round = READ_ONCE(ring_container->itr_scale) + 8;
avg_wire_size += BIT(itr_round) - 1;
avg_wire_size >>= itr_round;

Expand Down Expand Up @@ -1473,7 +1484,7 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
/* re-enable the q_vector */
fm10k_qv_enable(q_vector);

return 0;
return min(work_done, budget - 1);
}

/**
Expand Down
Loading

0 comments on commit 3201a39

Please sign in to comment.