Commit 3ca3f39c authored by David S. Miller's avatar David S. Miller

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

Tony Nguyen says:

====================
1GbE Intel Wired LAN Driver Updates 2021-03-29

This series contains updates to igc driver only.

Andre Guedes says:

Add XDP support for the igc driver. The approach implemented by this
series follows the same approach implemented in other Intel drivers as
much as possible for the sake of consistency.

The series is organized in two parts. In the first part, i.e. patches
from 1 to 4, igc_main.c and igc_ptp.c code is refactored in preparation
for landing the XDP support, which is introduced in the second part
(patches from 5 to 8).

As far as code organization is concerned, XDP-related helpers are
defined in a new file, igc_xdp.c, and are called by igc_main.c.

The features added by this series have been tested with the samples
provided in samples/bpf/: xdp1, xdp2, xdp_redirect_cpu, and
xdp_redirect_map.

Upcoming series will add support of UMEM and zero-copy features from
AF_XDP.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3af562a3 4ff32036
...@@ -8,4 +8,4 @@ ...@@ -8,4 +8,4 @@
obj-$(CONFIG_IGC) += igc.o obj-$(CONFIG_IGC) += igc.o
igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o igc_xdp.o
...@@ -111,6 +111,8 @@ struct igc_ring { ...@@ -111,6 +111,8 @@ struct igc_ring {
struct sk_buff *skb; struct sk_buff *skb;
}; };
}; };
struct xdp_rxq_info xdp_rxq;
} ____cacheline_internodealigned_in_smp; } ____cacheline_internodealigned_in_smp;
/* Board specific private data structure */ /* Board specific private data structure */
...@@ -219,6 +221,8 @@ struct igc_adapter { ...@@ -219,6 +221,8 @@ struct igc_adapter {
ktime_t ptp_reset_start; /* Reset time in clock mono */ ktime_t ptp_reset_start; /* Reset time in clock mono */
char fw_version[32]; char fw_version[32];
struct bpf_prog *xdp_prog;
}; };
void igc_up(struct igc_adapter *adapter); void igc_up(struct igc_adapter *adapter);
...@@ -373,6 +377,8 @@ enum igc_tx_flags { ...@@ -373,6 +377,8 @@ enum igc_tx_flags {
/* olinfo flags */ /* olinfo flags */
IGC_TX_FLAGS_IPV4 = 0x10, IGC_TX_FLAGS_IPV4 = 0x10,
IGC_TX_FLAGS_CSUM = 0x20, IGC_TX_FLAGS_CSUM = 0x20,
IGC_TX_FLAGS_XDP = 0x100,
}; };
enum igc_boards { enum igc_boards {
...@@ -395,7 +401,10 @@ enum igc_boards { ...@@ -395,7 +401,10 @@ enum igc_boards {
struct igc_tx_buffer { struct igc_tx_buffer {
union igc_adv_tx_desc *next_to_watch; union igc_adv_tx_desc *next_to_watch;
unsigned long time_stamp; unsigned long time_stamp;
struct sk_buff *skb; union {
struct sk_buff *skb;
struct xdp_frame *xdpf;
};
unsigned int bytecount; unsigned int bytecount;
u16 gso_segs; u16 gso_segs;
__be16 protocol; __be16 protocol;
...@@ -504,6 +513,10 @@ enum igc_ring_flags_t { ...@@ -504,6 +513,10 @@ enum igc_ring_flags_t {
#define ring_uses_large_buffer(ring) \ #define ring_uses_large_buffer(ring) \
test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags) test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
#define set_ring_uses_large_buffer(ring) \
set_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
#define clear_ring_uses_large_buffer(ring) \
clear_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
#define ring_uses_build_skb(ring) \ #define ring_uses_build_skb(ring) \
test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags) test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
...@@ -547,8 +560,7 @@ void igc_ptp_init(struct igc_adapter *adapter); ...@@ -547,8 +560,7 @@ void igc_ptp_init(struct igc_adapter *adapter);
void igc_ptp_reset(struct igc_adapter *adapter); void igc_ptp_reset(struct igc_adapter *adapter);
void igc_ptp_suspend(struct igc_adapter *adapter); void igc_ptp_suspend(struct igc_adapter *adapter);
void igc_ptp_stop(struct igc_adapter *adapter); void igc_ptp_stop(struct igc_adapter *adapter);
void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf);
struct sk_buff *skb);
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
void igc_ptp_tx_hang(struct igc_adapter *adapter); void igc_ptp_tx_hang(struct igc_adapter *adapter);
......
This diff is collapsed.
...@@ -153,20 +153,20 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter, ...@@ -153,20 +153,20 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
/** /**
* igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer * igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer
* @q_vector: Pointer to interrupt specific structure * @adapter: Pointer to adapter the packet buffer belongs to
* @va: Pointer to address containing Rx buffer * @buf: Pointer to packet buffer
* @skb: Buffer containing timestamp and packet
* *
* This function retrieves the timestamp saved in the beginning of packet * This function retrieves the timestamp saved in the beginning of packet
* buffer. While two timestamps are available, one in timer0 reference and the * buffer. While two timestamps are available, one in timer0 reference and the
* other in timer1 reference, this function considers only the timestamp in * other in timer1 reference, this function considers only the timestamp in
* timer0 reference. * timer0 reference.
*
* Returns timestamp value.
*/ */
void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf)
struct sk_buff *skb)
{ {
struct igc_adapter *adapter = q_vector->adapter; ktime_t timestamp;
u64 regval; u32 secs, nsecs;
int adjust; int adjust;
/* Timestamps are saved in little endian at the beginning of the packet /* Timestamps are saved in little endian at the beginning of the packet
...@@ -178,9 +178,10 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, ...@@ -178,9 +178,10 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
* SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds * SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds
* part of the timestamp. * part of the timestamp.
*/ */
regval = le32_to_cpu(va[2]); nsecs = le32_to_cpu(buf[2]);
regval |= (u64)le32_to_cpu(va[3]) << 32; secs = le32_to_cpu(buf[3]);
igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
timestamp = ktime_set(secs, nsecs);
/* Adjust timestamp for the RX latency based on link speed */ /* Adjust timestamp for the RX latency based on link speed */
switch (adapter->link_speed) { switch (adapter->link_speed) {
...@@ -201,8 +202,8 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va, ...@@ -201,8 +202,8 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
netdev_warn_once(adapter->netdev, "Imprecise timestamp\n"); netdev_warn_once(adapter->netdev, "Imprecise timestamp\n");
break; break;
} }
skb_hwtstamps(skb)->hwtstamp =
ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); return ktime_sub_ns(timestamp, adjust);
} }
static void igc_ptp_disable_rx_timestamp(struct igc_adapter *adapter) static void igc_ptp_disable_rx_timestamp(struct igc_adapter *adapter)
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020, Intel Corporation. */
#include "igc.h"
#include "igc_xdp.h"
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct netlink_ext_ack *extack)
{
struct net_device *dev = adapter->netdev;
bool if_running = netif_running(dev);
struct bpf_prog *old_prog;
if (dev->mtu > ETH_DATA_LEN) {
/* For now, the driver doesn't support XDP functionality with
* jumbo frames so we return error.
*/
NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
return -EOPNOTSUPP;
}
if (if_running)
igc_close(dev);
old_prog = xchg(&adapter->xdp_prog, prog);
if (old_prog)
bpf_prog_put(old_prog);
if (if_running)
igc_open(dev);
return 0;
}
int igc_xdp_register_rxq_info(struct igc_ring *ring)
{
struct net_device *dev = ring->netdev;
int err;
err = xdp_rxq_info_reg(&ring->xdp_rxq, dev, ring->queue_index, 0);
if (err) {
netdev_err(dev, "Failed to register xdp rxq info\n");
return err;
}
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, MEM_TYPE_PAGE_SHARED,
NULL);
if (err) {
netdev_err(dev, "Failed to register xdp rxq mem model\n");
xdp_rxq_info_unreg(&ring->xdp_rxq);
return err;
}
return 0;
}
void igc_xdp_unregister_rxq_info(struct igc_ring *ring)
{
xdp_rxq_info_unreg(&ring->xdp_rxq);
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020, Intel Corporation. */
#ifndef _IGC_XDP_H_
#define _IGC_XDP_H_
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct netlink_ext_ack *extack);
int igc_xdp_register_rxq_info(struct igc_ring *ring);
void igc_xdp_unregister_rxq_info(struct igc_ring *ring);
#endif /* _IGC_XDP_H_ */
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