Commit 13d5a30a authored by David S. Miller's avatar David S. Miller

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

Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2018-03-26

This series contains updates to i40e only.

Jake provides several patches which remove the need for cmpxchg64(),
starting with moving I40E_FLAG_[UDP]_FILTER_SYNC from pf->flags to pf->state
since they are modified during run time possibly when the RTNL lock is not
held so they should be a state bits and not flags.  Moved additional
"flags" which should be state fields, into pf->state.  Ensure we hold
the RTNL lock for the entire sequence of preparing for reset and when
resuming, which will protect the flags related to interrupt scheme under
RTNL lock so that their modification is properly threaded.  Finally,
cleanup the use of cmpxchg64() since it is no longer needed.  Cleaned up
the holes in the feature flags created my moving some flags to the state
field.

Björn Töpel adds XDP_REDIRECT support as well as tweaking the page
counting for XDP_REDIRECT so that it will function properly.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 34fd03b9 d9314c47
......@@ -159,9 +159,17 @@ enum i40e_state_t {
__I40E_BAD_EEPROM,
__I40E_DOWN_REQUESTED,
__I40E_FD_FLUSH_REQUESTED,
__I40E_FD_ATR_AUTO_DISABLED,
__I40E_FD_SB_AUTO_DISABLED,
__I40E_RESET_FAILED,
__I40E_PORT_SUSPENDED,
__I40E_VF_DISABLE,
__I40E_MACVLAN_SYNC_PENDING,
__I40E_UDP_FILTER_SYNC_PENDING,
__I40E_TEMP_LINK_POLLING,
__I40E_CLIENT_SERVICE_REQUESTED,
__I40E_CLIENT_L2_CHANGE,
__I40E_CLIENT_RESET,
/* This must be last as it determines the size of the BITMAP */
__I40E_STATE_SIZE__,
};
......@@ -510,40 +518,32 @@ struct i40e_pf {
#define I40E_HW_RESTART_AUTONEG BIT(18)
#define I40E_HW_STOPPABLE_FW_LLDP BIT(19)
u64 flags;
#define I40E_FLAG_RX_CSUM_ENABLED BIT_ULL(0)
#define I40E_FLAG_MSI_ENABLED BIT_ULL(1)
#define I40E_FLAG_MSIX_ENABLED BIT_ULL(2)
#define I40E_FLAG_RSS_ENABLED BIT_ULL(3)
#define I40E_FLAG_VMDQ_ENABLED BIT_ULL(4)
#define I40E_FLAG_FILTER_SYNC BIT_ULL(5)
#define I40E_FLAG_SRIOV_ENABLED BIT_ULL(6)
#define I40E_FLAG_DCB_CAPABLE BIT_ULL(7)
#define I40E_FLAG_DCB_ENABLED BIT_ULL(8)
#define I40E_FLAG_FD_SB_ENABLED BIT_ULL(9)
#define I40E_FLAG_FD_ATR_ENABLED BIT_ULL(10)
#define I40E_FLAG_FD_SB_AUTO_DISABLED BIT_ULL(11)
#define I40E_FLAG_FD_ATR_AUTO_DISABLED BIT_ULL(12)
#define I40E_FLAG_MFP_ENABLED BIT_ULL(13)
#define I40E_FLAG_UDP_FILTER_SYNC BIT_ULL(14)
#define I40E_FLAG_HW_ATR_EVICT_ENABLED BIT_ULL(15)
#define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(16)
#define I40E_FLAG_VEB_STATS_ENABLED BIT_ULL(17)
#define I40E_FLAG_LINK_POLLING_ENABLED BIT_ULL(18)
#define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT_ULL(19)
#define I40E_FLAG_TEMP_LINK_POLLING BIT_ULL(20)
#define I40E_FLAG_LEGACY_RX BIT_ULL(21)
#define I40E_FLAG_PTP BIT_ULL(22)
#define I40E_FLAG_IWARP_ENABLED BIT_ULL(23)
#define I40E_FLAG_SERVICE_CLIENT_REQUESTED BIT_ULL(24)
#define I40E_FLAG_CLIENT_L2_CHANGE BIT_ULL(25)
#define I40E_FLAG_CLIENT_RESET BIT_ULL(26)
#define I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED BIT_ULL(27)
#define I40E_FLAG_SOURCE_PRUNING_DISABLED BIT_ULL(28)
#define I40E_FLAG_TC_MQPRIO BIT_ULL(29)
#define I40E_FLAG_FD_SB_INACTIVE BIT_ULL(30)
#define I40E_FLAG_FD_SB_TO_CLOUD_FILTER BIT_ULL(31)
#define I40E_FLAG_DISABLE_FW_LLDP BIT_ULL(32)
u32 flags;
#define I40E_FLAG_RX_CSUM_ENABLED BIT(0)
#define I40E_FLAG_MSI_ENABLED BIT(1)
#define I40E_FLAG_MSIX_ENABLED BIT(2)
#define I40E_FLAG_RSS_ENABLED BIT(3)
#define I40E_FLAG_VMDQ_ENABLED BIT(4)
#define I40E_FLAG_SRIOV_ENABLED BIT(5)
#define I40E_FLAG_DCB_CAPABLE BIT(6)
#define I40E_FLAG_DCB_ENABLED BIT(7)
#define I40E_FLAG_FD_SB_ENABLED BIT(8)
#define I40E_FLAG_FD_ATR_ENABLED BIT(9)
#define I40E_FLAG_MFP_ENABLED BIT(10)
#define I40E_FLAG_HW_ATR_EVICT_ENABLED BIT(11)
#define I40E_FLAG_VEB_MODE_ENABLED BIT(12)
#define I40E_FLAG_VEB_STATS_ENABLED BIT(13)
#define I40E_FLAG_LINK_POLLING_ENABLED BIT(14)
#define I40E_FLAG_TRUE_PROMISC_SUPPORT BIT(15)
#define I40E_FLAG_LEGACY_RX BIT(16)
#define I40E_FLAG_PTP BIT(17)
#define I40E_FLAG_IWARP_ENABLED BIT(18)
#define I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED BIT(19)
#define I40E_FLAG_SOURCE_PRUNING_DISABLED BIT(20)
#define I40E_FLAG_TC_MQPRIO BIT(21)
#define I40E_FLAG_FD_SB_INACTIVE BIT(22)
#define I40E_FLAG_FD_SB_TO_CLOUD_FILTER BIT(23)
#define I40E_FLAG_DISABLE_FW_LLDP BIT(24)
struct i40e_client_instance *cinst;
bool stat_offsets_loaded;
......
......@@ -376,9 +376,8 @@ void i40e_client_subtask(struct i40e_pf *pf)
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
int ret = 0;
if (!(pf->flags & I40E_FLAG_SERVICE_CLIENT_REQUESTED))
if (!test_and_clear_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state))
return;
pf->flags &= ~I40E_FLAG_SERVICE_CLIENT_REQUESTED;
cdev = pf->cinst;
/* If we're down or resetting, just bail */
......@@ -459,7 +458,7 @@ int i40e_lan_add_device(struct i40e_pf *pf)
* added, we can schedule a subtask to go initiate the clients if
* they can be launched at probe time.
*/
pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state);
i40e_service_event_schedule(pf);
out:
......@@ -554,7 +553,7 @@ static void i40e_client_prepare(struct i40e_client *client)
pf = ldev->pf;
i40e_client_add_instance(pf);
/* Start the client subtask */
pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED;
set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state);
i40e_service_event_schedule(pf);
}
mutex_unlock(&i40e_device_mutex);
......
......@@ -3951,7 +3951,7 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
return -EOPNOTSUPP;
if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED)
if (test_bit(__I40E_FD_SB_AUTO_DISABLED, pf->state))
return -ENOSPC;
if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
......@@ -4436,21 +4436,12 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
}
}
/* Compare and exchange the new flags into place. If we failed, that
* is if cmpxchg returns anything but the old value, this means that
* something else has modified the flags variable since we copied it
* originally. We'll just punt with an error and log something in the
* message buffer.
*
* This is the point of no return for this function. We need to have
* checked any discrepancies or misconfigurations and returned
* EOPNOTSUPP before updating pf->flags here.
/* Now that we've checked to ensure that the new flags are valid, load
* them into place. Since we only modify flags either (a) during
* initialization or (b) while holding the RTNL lock, we don't need
* anything fancy here.
*/
if (cmpxchg64(&pf->flags, orig_flags, new_flags) != orig_flags) {
dev_warn(&pf->pdev->dev,
"Unable to update pf->flags as it was modified by another thread...\n");
return -EAGAIN;
}
pf->flags = new_flags;
/* Process any additional changes needed as a result of flag changes.
* The changed_flags value reflects the list of bits that were
......@@ -4460,7 +4451,7 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
/* Flush current ATR settings if ATR was disabled */
if ((changed_flags & I40E_FLAG_FD_ATR_ENABLED) &&
!(pf->flags & I40E_FLAG_FD_ATR_ENABLED)) {
pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
set_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state);
set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
}
......
This diff is collapsed.
......@@ -336,7 +336,7 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
I40E_DEBUG_FD & pf->hw.debug_mask)
dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n");
pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
set_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state);
} else {
pf->fd_tcp4_filter_cnt--;
}
......@@ -594,8 +594,14 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
pf->fd_atr_cnt = i40e_get_current_atr_cnt(pf);
if ((rx_desc->wb.qword0.hi_dword.fd_id == 0) &&
pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
test_bit(__I40E_FD_SB_AUTO_DISABLED, pf->state)) {
/* These set_bit() calls aren't atomic with the
* test_bit() here, but worse case we potentially
* disable ATR and queue a flush right after SB
* support is re-enabled. That shouldn't cause an
* issue in practice
*/
set_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state);
set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
}
......@@ -608,12 +614,11 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
*/
if (fcnt_prog >= (fcnt_avail - I40E_FDIR_BUFFER_FULL_MARGIN)) {
if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
!(pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED)) {
pf->flags |= I40E_FLAG_FD_SB_AUTO_DISABLED;
!test_and_set_bit(__I40E_FD_SB_AUTO_DISABLED,
pf->state))
if (I40E_DEBUG_FD & pf->hw.debug_mask)
dev_warn(&pdev->dev, "FD filter space full, new ntuple rules will not be added\n");
}
}
} else if (error == BIT(I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
if (I40E_DEBUG_FD & pf->hw.debug_mask)
dev_info(&pdev->dev, "ntuple filter fd_id = %d, could not be removed\n",
......@@ -1583,9 +1588,8 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
bi->dma = dma;
bi->page = page;
bi->page_offset = i40e_rx_offset(rx_ring);
/* initialize pagecnt_bias to 1 representing we fully own page */
bi->pagecnt_bias = 1;
page_ref_add(page, USHRT_MAX - 1);
bi->pagecnt_bias = USHRT_MAX;
return true;
}
......@@ -1951,8 +1955,8 @@ static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer)
* the pagecnt_bias and page count so that we fully restock the
* number of references the driver holds.
*/
if (unlikely(!pagecnt_bias)) {
page_ref_add(page, USHRT_MAX);
if (unlikely(pagecnt_bias == 1)) {
page_ref_add(page, USHRT_MAX - 1);
rx_buffer->pagecnt_bias = USHRT_MAX;
}
......@@ -2210,7 +2214,7 @@ static int i40e_xmit_xdp_ring(struct xdp_buff *xdp,
static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring,
struct xdp_buff *xdp)
{
int result = I40E_XDP_PASS;
int err, result = I40E_XDP_PASS;
struct i40e_ring *xdp_ring;
struct bpf_prog *xdp_prog;
u32 act;
......@@ -2229,6 +2233,10 @@ static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring,
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
result = i40e_xmit_xdp_ring(xdp, xdp_ring);
break;
case XDP_REDIRECT:
err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
result = !err ? I40E_XDP_TX : I40E_XDP_CONSUMED;
break;
default:
bpf_warn_invalid_xdp_action(act);
case XDP_ABORTED:
......@@ -2264,6 +2272,15 @@ static void i40e_rx_buffer_flip(struct i40e_ring *rx_ring,
#endif
}
static inline void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring)
{
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch.
*/
wmb();
writel_relaxed(xdp_ring->next_to_use, xdp_ring->tail);
}
/**
* i40e_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
* @rx_ring: rx descriptor ring to transact packets on
......@@ -2398,16 +2415,11 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
}
if (xdp_xmit) {
struct i40e_ring *xdp_ring;
struct i40e_ring *xdp_ring =
rx_ring->vsi->xdp_rings[rx_ring->queue_index];
xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch.
*/
wmb();
writel(xdp_ring->next_to_use, xdp_ring->tail);
i40e_xdp_ring_update_tail(xdp_ring);
xdp_do_flush_map();
}
rx_ring->skb = skb;
......@@ -2647,7 +2659,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED))
return;
if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED)
if (test_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state))
return;
/* if sampling is disabled do nothing */
......@@ -2687,7 +2699,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
th = (struct tcphdr *)(hdr.network + hlen);
/* Due to lack of space, no more new filters can be programmed */
if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
if (th->syn && test_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state))
return;
if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) {
/* HW ATR eviction will take care of removing filters on FIN
......@@ -3655,3 +3667,49 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return i40e_xmit_frame_ring(skb, tx_ring);
}
/**
* i40e_xdp_xmit - Implements ndo_xdp_xmit
* @dev: netdev
* @xdp: XDP buffer
*
* Returns Zero if sent, else an error code
**/
int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
unsigned int queue_index = smp_processor_id();
struct i40e_vsi *vsi = np->vsi;
int err;
if (test_bit(__I40E_VSI_DOWN, vsi->state))
return -ENETDOWN;
if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
return -ENXIO;
err = i40e_xmit_xdp_ring(xdp, vsi->xdp_rings[queue_index]);
if (err != I40E_XDP_TX)
return -ENOSPC;
return 0;
}
/**
* i40e_xdp_flush - Implements ndo_xdp_flush
* @dev: netdev
**/
void i40e_xdp_flush(struct net_device *dev)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
unsigned int queue_index = smp_processor_id();
struct i40e_vsi *vsi = np->vsi;
if (test_bit(__I40E_VSI_DOWN, vsi->state))
return;
if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
return;
i40e_xdp_ring_update_tail(vsi->xdp_rings[queue_index]);
}
......@@ -510,6 +510,8 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw);
void i40e_detect_recover_hung(struct i40e_vsi *vsi);
int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
bool __i40e_chk_linearize(struct sk_buff *skb);
int i40e_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp);
void i40e_xdp_flush(struct net_device *dev);
/**
* i40e_get_head - Retrieve head from head writeback
......
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