Commit c08bac03 authored by David S. Miller's avatar David S. Miller

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

Jeff Kirsher says:

====================
10GbE Intel Wired LAN Driver Updates 2017-04-29

This series contains updates to ixgbe and ixgbevf only, most notable is
the addition of XDP support to our 10GbE drivers.

Paul fixes ixgbe to acquire the PHY semaphore before accessing PHY
registers when issuing a device reset.

John adds XDP support (yeah!) for ixgbe.

Emil fixes an issue by flushing the MACVLAN filters on VF reset to avoid
conflicts with other VFs that may end up using the same MAC address.  Also
fixed a bug where ethtool -S displayed some empty fields for ixgbevf
because it was using ixgbe_stats instead ixgbevf_stats for
IXGBEVF_QUEUE_STATS_LEN.

Tony adds the ability to specify a zero MAC address in order to clear the
VF's MAC address from the RAR table.  Also adds support for a new
1000Base-T device based on x550EM_X MAC type.  Fixed an issue where the
RSS key specified by the user would be over-written with a pre-existing
value, so change the rss_key to a pointer so we can check to see if the
key has a value set before attempting to set it.  Fixed the logic for
mailbox support for getting RETA and RSS values, which are only supported
by 82599 and x540 devices.

v2: fixed up patches #2 and #3 based on feedback from Jakub and to
    address build issues when page sizes are larger than 4k
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4c042a80 e60ae003
...@@ -235,7 +235,11 @@ struct vf_macvlans { ...@@ -235,7 +235,11 @@ struct vf_macvlans {
struct ixgbe_tx_buffer { struct ixgbe_tx_buffer {
union ixgbe_adv_tx_desc *next_to_watch; union ixgbe_adv_tx_desc *next_to_watch;
unsigned long time_stamp; unsigned long time_stamp;
struct sk_buff *skb; union {
struct sk_buff *skb;
/* XDP uses address ptr on irq_clean */
void *data;
};
unsigned int bytecount; unsigned int bytecount;
unsigned short gso_segs; unsigned short gso_segs;
__be16 protocol; __be16 protocol;
...@@ -288,6 +292,7 @@ enum ixgbe_ring_state_t { ...@@ -288,6 +292,7 @@ enum ixgbe_ring_state_t {
__IXGBE_TX_XPS_INIT_DONE, __IXGBE_TX_XPS_INIT_DONE,
__IXGBE_TX_DETECT_HANG, __IXGBE_TX_DETECT_HANG,
__IXGBE_HANG_CHECK_ARMED, __IXGBE_HANG_CHECK_ARMED,
__IXGBE_TX_XDP_RING,
}; };
#define ring_uses_build_skb(ring) \ #define ring_uses_build_skb(ring) \
...@@ -314,10 +319,17 @@ struct ixgbe_fwd_adapter { ...@@ -314,10 +319,17 @@ struct ixgbe_fwd_adapter {
set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
#define clear_ring_rsc_enabled(ring) \ #define clear_ring_rsc_enabled(ring) \
clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state)
#define ring_is_xdp(ring) \
test_bit(__IXGBE_TX_XDP_RING, &(ring)->state)
#define set_ring_xdp(ring) \
set_bit(__IXGBE_TX_XDP_RING, &(ring)->state)
#define clear_ring_xdp(ring) \
clear_bit(__IXGBE_TX_XDP_RING, &(ring)->state)
struct ixgbe_ring { struct ixgbe_ring {
struct ixgbe_ring *next; /* pointer to next ring in q_vector */ struct ixgbe_ring *next; /* pointer to next ring in q_vector */
struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */ struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */
struct net_device *netdev; /* netdev ring belongs to */ struct net_device *netdev; /* netdev ring belongs to */
struct bpf_prog *xdp_prog;
struct device *dev; /* device for DMA mapping */ struct device *dev; /* device for DMA mapping */
struct ixgbe_fwd_adapter *l2_accel_priv; struct ixgbe_fwd_adapter *l2_accel_priv;
void *desc; /* descriptor ring memory */ void *desc; /* descriptor ring memory */
...@@ -379,6 +391,7 @@ enum ixgbe_ring_f_enum { ...@@ -379,6 +391,7 @@ enum ixgbe_ring_f_enum {
#define IXGBE_MAX_FCOE_INDICES 8 #define IXGBE_MAX_FCOE_INDICES 8
#define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1) #define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
#define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1) #define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
#define MAX_XDP_QUEUES (IXGBE_MAX_FDIR_INDICES + 1)
#define IXGBE_MAX_L2A_QUEUES 4 #define IXGBE_MAX_L2A_QUEUES 4
#define IXGBE_BAD_L2A_QUEUE 3 #define IXGBE_BAD_L2A_QUEUE 3
#define IXGBE_MAX_MACVLANS 31 #define IXGBE_MAX_MACVLANS 31
...@@ -555,6 +568,7 @@ struct ixgbe_adapter { ...@@ -555,6 +568,7 @@ struct ixgbe_adapter {
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
/* OS defined structs */ /* OS defined structs */
struct net_device *netdev; struct net_device *netdev;
struct bpf_prog *xdp_prog;
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned long state; unsigned long state;
...@@ -621,6 +635,10 @@ struct ixgbe_adapter { ...@@ -621,6 +635,10 @@ struct ixgbe_adapter {
__be16 vxlan_port; __be16 vxlan_port;
__be16 geneve_port; __be16 geneve_port;
/* XDP */
int num_xdp_queues;
struct ixgbe_ring *xdp_ring[MAX_XDP_QUEUES];
/* TX */ /* TX */
struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp;
...@@ -667,6 +685,7 @@ struct ixgbe_adapter { ...@@ -667,6 +685,7 @@ struct ixgbe_adapter {
u64 tx_busy; u64 tx_busy;
unsigned int tx_ring_count; unsigned int tx_ring_count;
unsigned int xdp_ring_count;
unsigned int rx_ring_count; unsigned int rx_ring_count;
u32 link_speed; u32 link_speed;
...@@ -750,7 +769,7 @@ struct ixgbe_adapter { ...@@ -750,7 +769,7 @@ struct ixgbe_adapter {
u8 rss_indir_tbl[IXGBE_MAX_RETA_ENTRIES]; u8 rss_indir_tbl[IXGBE_MAX_RETA_ENTRIES];
#define IXGBE_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ #define IXGBE_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
u32 rss_key[IXGBE_RSS_KEY_SIZE / sizeof(u32)]; u32 *rss_key;
}; };
static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter) static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
...@@ -807,6 +826,7 @@ enum ixgbe_boards { ...@@ -807,6 +826,7 @@ enum ixgbe_boards {
board_X540, board_X540,
board_X550, board_X550,
board_X550EM_x, board_X550EM_x,
board_x550em_x_fw,
board_x550em_a, board_x550em_a,
board_x550em_a_fw, board_x550em_a_fw,
}; };
...@@ -816,6 +836,7 @@ extern const struct ixgbe_info ixgbe_82599_info; ...@@ -816,6 +836,7 @@ extern const struct ixgbe_info ixgbe_82599_info;
extern const struct ixgbe_info ixgbe_X540_info; extern const struct ixgbe_info ixgbe_X540_info;
extern const struct ixgbe_info ixgbe_X550_info; extern const struct ixgbe_info ixgbe_X550_info;
extern const struct ixgbe_info ixgbe_X550EM_x_info; extern const struct ixgbe_info ixgbe_X550EM_x_info;
extern const struct ixgbe_info ixgbe_x550em_x_fw_info;
extern const struct ixgbe_info ixgbe_x550em_a_info; extern const struct ixgbe_info ixgbe_x550em_a_info;
extern const struct ixgbe_info ixgbe_x550em_a_fw_info; extern const struct ixgbe_info ixgbe_x550em_a_fw_info;
#ifdef CONFIG_IXGBE_DCB #ifdef CONFIG_IXGBE_DCB
...@@ -835,7 +856,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter); ...@@ -835,7 +856,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter);
void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
void ixgbe_reset(struct ixgbe_adapter *adapter); void ixgbe_reset(struct ixgbe_adapter *adapter);
void ixgbe_set_ethtool_ops(struct net_device *netdev); void ixgbe_set_ethtool_ops(struct net_device *netdev);
int ixgbe_setup_rx_resources(struct ixgbe_ring *); int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
int ixgbe_setup_tx_resources(struct ixgbe_ring *); int ixgbe_setup_tx_resources(struct ixgbe_ring *);
void ixgbe_free_rx_resources(struct ixgbe_ring *); void ixgbe_free_rx_resources(struct ixgbe_ring *);
void ixgbe_free_tx_resources(struct ixgbe_ring *); void ixgbe_free_tx_resources(struct ixgbe_ring *);
......
...@@ -1071,15 +1071,19 @@ static int ixgbe_set_ringparam(struct net_device *netdev, ...@@ -1071,15 +1071,19 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
if (!netif_running(adapter->netdev)) { if (!netif_running(adapter->netdev)) {
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
adapter->tx_ring[i]->count = new_tx_count; adapter->tx_ring[i]->count = new_tx_count;
for (i = 0; i < adapter->num_xdp_queues; i++)
adapter->xdp_ring[i]->count = new_tx_count;
for (i = 0; i < adapter->num_rx_queues; i++) for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->count = new_rx_count; adapter->rx_ring[i]->count = new_rx_count;
adapter->tx_ring_count = new_tx_count; adapter->tx_ring_count = new_tx_count;
adapter->xdp_ring_count = new_tx_count;
adapter->rx_ring_count = new_rx_count; adapter->rx_ring_count = new_rx_count;
goto clear_reset; goto clear_reset;
} }
/* allocate temporary buffer to store rings in */ /* allocate temporary buffer to store rings in */
i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues); i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues);
i = max_t(int, i, adapter->num_xdp_queues);
temp_ring = vmalloc(i * sizeof(struct ixgbe_ring)); temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
if (!temp_ring) { if (!temp_ring) {
...@@ -1111,12 +1115,33 @@ static int ixgbe_set_ringparam(struct net_device *netdev, ...@@ -1111,12 +1115,33 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
} }
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
memcpy(&temp_ring[i], adapter->xdp_ring[i],
sizeof(struct ixgbe_ring));
temp_ring[i].count = new_tx_count;
err = ixgbe_setup_tx_resources(&temp_ring[i]);
if (err) {
while (i) {
i--;
ixgbe_free_tx_resources(&temp_ring[i]);
}
goto err_setup;
}
}
for (i = 0; i < adapter->num_tx_queues; i++) { for (i = 0; i < adapter->num_tx_queues; i++) {
ixgbe_free_tx_resources(adapter->tx_ring[i]); ixgbe_free_tx_resources(adapter->tx_ring[i]);
memcpy(adapter->tx_ring[i], &temp_ring[i], memcpy(adapter->tx_ring[i], &temp_ring[i],
sizeof(struct ixgbe_ring)); sizeof(struct ixgbe_ring));
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
ixgbe_free_tx_resources(adapter->xdp_ring[i]);
memcpy(adapter->xdp_ring[i], &temp_ring[i],
sizeof(struct ixgbe_ring));
}
adapter->tx_ring_count = new_tx_count; adapter->tx_ring_count = new_tx_count;
} }
...@@ -1128,7 +1153,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, ...@@ -1128,7 +1153,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
sizeof(struct ixgbe_ring)); sizeof(struct ixgbe_ring));
temp_ring[i].count = new_rx_count; temp_ring[i].count = new_rx_count;
err = ixgbe_setup_rx_resources(&temp_ring[i]); err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]);
if (err) { if (err) {
while (i) { while (i) {
i--; i--;
...@@ -1761,7 +1786,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) ...@@ -1761,7 +1786,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
rx_ring->netdev = adapter->netdev; rx_ring->netdev = adapter->netdev;
rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx; rx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;
err = ixgbe_setup_rx_resources(rx_ring); err = ixgbe_setup_rx_resources(adapter, rx_ring);
if (err) { if (err) {
ret_val = 4; ret_val = 4;
goto err_nomem; goto err_nomem;
...@@ -2942,9 +2967,7 @@ static int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter) ...@@ -2942,9 +2967,7 @@ static int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter)
static u32 ixgbe_get_rxfh_key_size(struct net_device *netdev) static u32 ixgbe_get_rxfh_key_size(struct net_device *netdev)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); return IXGBE_RSS_KEY_SIZE;
return sizeof(adapter->rss_key);
} }
static u32 ixgbe_rss_indir_size(struct net_device *netdev) static u32 ixgbe_rss_indir_size(struct net_device *netdev)
......
...@@ -267,12 +267,14 @@ static bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) ...@@ -267,12 +267,14 @@ static bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
**/ **/
static bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) static bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
{ {
int i; int i, reg_idx;
for (i = 0; i < adapter->num_rx_queues; i++) for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->reg_idx = i; adapter->rx_ring[i]->reg_idx = i;
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0, reg_idx = 0; i < adapter->num_tx_queues; i++, reg_idx++)
adapter->tx_ring[i]->reg_idx = i; adapter->tx_ring[i]->reg_idx = reg_idx;
for (i = 0; i < adapter->num_xdp_queues; i++, reg_idx++)
adapter->xdp_ring[i]->reg_idx = reg_idx;
return true; return true;
} }
...@@ -308,6 +310,11 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) ...@@ -308,6 +310,11 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
ixgbe_cache_ring_rss(adapter); ixgbe_cache_ring_rss(adapter);
} }
static int ixgbe_xdp_queues(struct ixgbe_adapter *adapter)
{
return adapter->xdp_prog ? nr_cpu_ids : 0;
}
#define IXGBE_RSS_64Q_MASK 0x3F #define IXGBE_RSS_64Q_MASK 0x3F
#define IXGBE_RSS_16Q_MASK 0xF #define IXGBE_RSS_16Q_MASK 0xF
#define IXGBE_RSS_8Q_MASK 0x7 #define IXGBE_RSS_8Q_MASK 0x7
...@@ -382,6 +389,7 @@ static bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter) ...@@ -382,6 +389,7 @@ static bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter)
adapter->num_rx_queues_per_pool = tcs; adapter->num_rx_queues_per_pool = tcs;
adapter->num_tx_queues = vmdq_i * tcs; adapter->num_tx_queues = vmdq_i * tcs;
adapter->num_xdp_queues = 0;
adapter->num_rx_queues = vmdq_i * tcs; adapter->num_rx_queues = vmdq_i * tcs;
#ifdef IXGBE_FCOE #ifdef IXGBE_FCOE
...@@ -479,6 +487,7 @@ static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) ...@@ -479,6 +487,7 @@ static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
netdev_set_tc_queue(dev, i, rss_i, rss_i * i); netdev_set_tc_queue(dev, i, rss_i, rss_i * i);
adapter->num_tx_queues = rss_i * tcs; adapter->num_tx_queues = rss_i * tcs;
adapter->num_xdp_queues = 0;
adapter->num_rx_queues = rss_i * tcs; adapter->num_rx_queues = rss_i * tcs;
return true; return true;
...@@ -549,6 +558,7 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) ...@@ -549,6 +558,7 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
adapter->num_rx_queues = vmdq_i * rss_i; adapter->num_rx_queues = vmdq_i * rss_i;
adapter->num_tx_queues = vmdq_i * rss_i; adapter->num_tx_queues = vmdq_i * rss_i;
adapter->num_xdp_queues = 0;
/* disable ATR as it is not supported when VMDq is enabled */ /* disable ATR as it is not supported when VMDq is enabled */
adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
...@@ -669,6 +679,7 @@ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) ...@@ -669,6 +679,7 @@ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter)
#endif /* IXGBE_FCOE */ #endif /* IXGBE_FCOE */
adapter->num_rx_queues = rss_i; adapter->num_rx_queues = rss_i;
adapter->num_tx_queues = rss_i; adapter->num_tx_queues = rss_i;
adapter->num_xdp_queues = ixgbe_xdp_queues(adapter);
return true; return true;
} }
...@@ -689,6 +700,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) ...@@ -689,6 +700,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
/* Start with base case */ /* Start with base case */
adapter->num_rx_queues = 1; adapter->num_rx_queues = 1;
adapter->num_tx_queues = 1; adapter->num_tx_queues = 1;
adapter->num_xdp_queues = 0;
adapter->num_rx_pools = adapter->num_rx_queues; adapter->num_rx_pools = adapter->num_rx_queues;
adapter->num_rx_queues_per_pool = 1; adapter->num_rx_queues_per_pool = 1;
...@@ -719,8 +731,11 @@ static int ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter) ...@@ -719,8 +731,11 @@ static int ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
int i, vectors, vector_threshold; int i, vectors, vector_threshold;
/* We start by asking for one vector per queue pair */ /* We start by asking for one vector per queue pair with XDP queues
* being stacked with TX queues.
*/
vectors = max(adapter->num_rx_queues, adapter->num_tx_queues); vectors = max(adapter->num_rx_queues, adapter->num_tx_queues);
vectors = max(vectors, adapter->num_xdp_queues);
/* It is easy to be greedy for MSI-X vectors. However, it really /* It is easy to be greedy for MSI-X vectors. However, it really
* doesn't do much good if we have a lot more vectors than CPUs. We'll * doesn't do much good if we have a lot more vectors than CPUs. We'll
...@@ -800,6 +815,8 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring, ...@@ -800,6 +815,8 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring,
* @v_idx: index of vector in adapter struct * @v_idx: index of vector in adapter struct
* @txr_count: total number of Tx rings to allocate * @txr_count: total number of Tx rings to allocate
* @txr_idx: index of first Tx ring to allocate * @txr_idx: index of first Tx ring to allocate
* @xdp_count: total number of XDP rings to allocate
* @xdp_idx: index of first XDP ring to allocate
* @rxr_count: total number of Rx rings to allocate * @rxr_count: total number of Rx rings to allocate
* @rxr_idx: index of first Rx ring to allocate * @rxr_idx: index of first Rx ring to allocate
* *
...@@ -808,6 +825,7 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring, ...@@ -808,6 +825,7 @@ static void ixgbe_add_ring(struct ixgbe_ring *ring,
static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
int v_count, int v_idx, int v_count, int v_idx,
int txr_count, int txr_idx, int txr_count, int txr_idx,
int xdp_count, int xdp_idx,
int rxr_count, int rxr_idx) int rxr_count, int rxr_idx)
{ {
struct ixgbe_q_vector *q_vector; struct ixgbe_q_vector *q_vector;
...@@ -817,7 +835,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, ...@@ -817,7 +835,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
int ring_count, size; int ring_count, size;
u8 tcs = netdev_get_num_tc(adapter->netdev); u8 tcs = netdev_get_num_tc(adapter->netdev);
ring_count = txr_count + rxr_count; ring_count = txr_count + rxr_count + xdp_count;
size = sizeof(struct ixgbe_q_vector) + size = sizeof(struct ixgbe_q_vector) +
(sizeof(struct ixgbe_ring) * ring_count); (sizeof(struct ixgbe_ring) * ring_count);
...@@ -909,6 +927,33 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, ...@@ -909,6 +927,33 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
ring++; ring++;
} }
while (xdp_count) {
/* assign generic ring traits */
ring->dev = &adapter->pdev->dev;
ring->netdev = adapter->netdev;
/* configure backlink on ring */
ring->q_vector = q_vector;
/* update q_vector Tx values */
ixgbe_add_ring(ring, &q_vector->tx);
/* apply Tx specific ring traits */
ring->count = adapter->tx_ring_count;
ring->queue_index = xdp_idx;
set_ring_xdp(ring);
/* assign ring to adapter */
adapter->xdp_ring[xdp_idx] = ring;
/* update count and index */
xdp_count--;
xdp_idx++;
/* push pointer to next ring */
ring++;
}
while (rxr_count) { while (rxr_count) {
/* assign generic ring traits */ /* assign generic ring traits */
ring->dev = &adapter->pdev->dev; ring->dev = &adapter->pdev->dev;
...@@ -1002,17 +1047,18 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) ...@@ -1002,17 +1047,18 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
int q_vectors = adapter->num_q_vectors; int q_vectors = adapter->num_q_vectors;
int rxr_remaining = adapter->num_rx_queues; int rxr_remaining = adapter->num_rx_queues;
int txr_remaining = adapter->num_tx_queues; int txr_remaining = adapter->num_tx_queues;
int rxr_idx = 0, txr_idx = 0, v_idx = 0; int xdp_remaining = adapter->num_xdp_queues;
int rxr_idx = 0, txr_idx = 0, xdp_idx = 0, v_idx = 0;
int err; int err;
/* only one q_vector if MSI-X is disabled. */ /* only one q_vector if MSI-X is disabled. */
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
q_vectors = 1; q_vectors = 1;
if (q_vectors >= (rxr_remaining + txr_remaining)) { if (q_vectors >= (rxr_remaining + txr_remaining + xdp_remaining)) {
for (; rxr_remaining; v_idx++) { for (; rxr_remaining; v_idx++) {
err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx, err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
0, 0, 1, rxr_idx); 0, 0, 0, 0, 1, rxr_idx);
if (err) if (err)
goto err_out; goto err_out;
...@@ -1026,8 +1072,11 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) ...@@ -1026,8 +1072,11 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
for (; v_idx < q_vectors; v_idx++) { for (; v_idx < q_vectors; v_idx++) {
int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
int xqpv = DIV_ROUND_UP(xdp_remaining, q_vectors - v_idx);
err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx, err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
tqpv, txr_idx, tqpv, txr_idx,
xqpv, xdp_idx,
rqpv, rxr_idx); rqpv, rxr_idx);
if (err) if (err)
...@@ -1036,14 +1085,17 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) ...@@ -1036,14 +1085,17 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
/* update counts and index */ /* update counts and index */
rxr_remaining -= rqpv; rxr_remaining -= rqpv;
txr_remaining -= tqpv; txr_remaining -= tqpv;
xdp_remaining -= xqpv;
rxr_idx++; rxr_idx++;
txr_idx++; txr_idx++;
xdp_idx += xqpv;
} }
return 0; return 0;
err_out: err_out:
adapter->num_tx_queues = 0; adapter->num_tx_queues = 0;
adapter->num_xdp_queues = 0;
adapter->num_rx_queues = 0; adapter->num_rx_queues = 0;
adapter->num_q_vectors = 0; adapter->num_q_vectors = 0;
...@@ -1066,6 +1118,7 @@ static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter) ...@@ -1066,6 +1118,7 @@ static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter)
int v_idx = adapter->num_q_vectors; int v_idx = adapter->num_q_vectors;
adapter->num_tx_queues = 0; adapter->num_tx_queues = 0;
adapter->num_xdp_queues = 0;
adapter->num_rx_queues = 0; adapter->num_rx_queues = 0;
adapter->num_q_vectors = 0; adapter->num_q_vectors = 0;
...@@ -1172,9 +1225,10 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) ...@@ -1172,9 +1225,10 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
ixgbe_cache_ring_register(adapter); ixgbe_cache_ring_register(adapter);
e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u\n", e_dev_info("Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u XDP Queue count = %u\n",
(adapter->num_rx_queues > 1) ? "Enabled" : "Disabled", (adapter->num_rx_queues > 1) ? "Enabled" : "Disabled",
adapter->num_rx_queues, adapter->num_tx_queues); adapter->num_rx_queues, adapter->num_tx_queues,
adapter->num_xdp_queues);
set_bit(__IXGBE_DOWN, &adapter->state); set_bit(__IXGBE_DOWN, &adapter->state);
...@@ -1195,6 +1249,7 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) ...@@ -1195,6 +1249,7 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
{ {
adapter->num_tx_queues = 0; adapter->num_tx_queues = 0;
adapter->num_xdp_queues = 0;
adapter->num_rx_queues = 0; adapter->num_rx_queues = 0;
ixgbe_free_q_vectors(adapter); ixgbe_free_q_vectors(adapter);
......
...@@ -49,6 +49,9 @@ ...@@ -49,6 +49,9 @@
#include <linux/if_macvlan.h> #include <linux/if_macvlan.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/bpf.h>
#include <linux/bpf_trace.h>
#include <linux/atomic.h>
#include <scsi/fc/fc_fcoe.h> #include <scsi/fc/fc_fcoe.h>
#include <net/udp_tunnel.h> #include <net/udp_tunnel.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
...@@ -85,6 +88,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { ...@@ -85,6 +88,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {
[board_X540] = &ixgbe_X540_info, [board_X540] = &ixgbe_X540_info,
[board_X550] = &ixgbe_X550_info, [board_X550] = &ixgbe_X550_info,
[board_X550EM_x] = &ixgbe_X550EM_x_info, [board_X550EM_x] = &ixgbe_X550EM_x_info,
[board_x550em_x_fw] = &ixgbe_x550em_x_fw_info,
[board_x550em_a] = &ixgbe_x550em_a_info, [board_x550em_a] = &ixgbe_x550em_a_info,
[board_x550em_a_fw] = &ixgbe_x550em_a_fw_info, [board_x550em_a_fw] = &ixgbe_x550em_a_fw_info,
}; };
...@@ -135,6 +139,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { ...@@ -135,6 +139,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_1G_T), board_x550em_x_fw},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR), board_x550em_a },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR_L), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_KR_L), board_x550em_a },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N), board_x550em_a }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP_N), board_x550em_a },
...@@ -590,6 +595,19 @@ static void ixgbe_regdump(struct ixgbe_hw *hw, struct ixgbe_reg_info *reginfo) ...@@ -590,6 +595,19 @@ static void ixgbe_regdump(struct ixgbe_hw *hw, struct ixgbe_reg_info *reginfo)
} }
static void ixgbe_print_buffer(struct ixgbe_ring *ring, int n)
{
struct ixgbe_tx_buffer *tx_buffer;
tx_buffer = &ring->tx_buffer_info[ring->next_to_clean];
pr_info(" %5d %5X %5X %016llX %08X %p %016llX\n",
n, ring->next_to_use, ring->next_to_clean,
(u64)dma_unmap_addr(tx_buffer, dma),
dma_unmap_len(tx_buffer, len),
tx_buffer->next_to_watch,
(u64)tx_buffer->time_stamp);
}
/* /*
* ixgbe_dump - Print registers, tx-rings and rx-rings * ixgbe_dump - Print registers, tx-rings and rx-rings
*/ */
...@@ -599,7 +617,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) ...@@ -599,7 +617,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_reg_info *reginfo; struct ixgbe_reg_info *reginfo;
int n = 0; int n = 0;
struct ixgbe_ring *tx_ring; struct ixgbe_ring *ring;
struct ixgbe_tx_buffer *tx_buffer; struct ixgbe_tx_buffer *tx_buffer;
union ixgbe_adv_tx_desc *tx_desc; union ixgbe_adv_tx_desc *tx_desc;
struct my_u0 { u64 a; u64 b; } *u0; struct my_u0 { u64 a; u64 b; } *u0;
...@@ -639,14 +657,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) ...@@ -639,14 +657,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
"Queue [NTU] [NTC] [bi(ntc)->dma ]", "Queue [NTU] [NTC] [bi(ntc)->dma ]",
"leng", "ntw", "timestamp"); "leng", "ntw", "timestamp");
for (n = 0; n < adapter->num_tx_queues; n++) { for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n]; ring = adapter->tx_ring[n];
tx_buffer = &tx_ring->tx_buffer_info[tx_ring->next_to_clean]; ixgbe_print_buffer(ring, n);
pr_info(" %5d %5X %5X %016llX %08X %p %016llX\n", }
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)dma_unmap_addr(tx_buffer, dma), for (n = 0; n < adapter->num_xdp_queues; n++) {
dma_unmap_len(tx_buffer, len), ring = adapter->xdp_ring[n];
tx_buffer->next_to_watch, ixgbe_print_buffer(ring, n);
(u64)tx_buffer->time_stamp);
} }
/* Print TX Rings */ /* Print TX Rings */
...@@ -691,28 +708,28 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter) ...@@ -691,28 +708,28 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
*/ */
for (n = 0; n < adapter->num_tx_queues; n++) { for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n]; ring = adapter->tx_ring[n];
pr_info("------------------------------------\n"); pr_info("------------------------------------\n");
pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index); pr_info("TX QUEUE INDEX = %d\n", ring->queue_index);
pr_info("------------------------------------\n"); pr_info("------------------------------------\n");
pr_info("%s%s %s %s %s %s\n", pr_info("%s%s %s %s %s %s\n",
"T [desc] [address 63:0 ] ", "T [desc] [address 63:0 ] ",
"[PlPOIdStDDt Ln] [bi->dma ] ", "[PlPOIdStDDt Ln] [bi->dma ] ",
"leng", "ntw", "timestamp", "bi->skb"); "leng", "ntw", "timestamp", "bi->skb");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { for (i = 0; ring->desc && (i < ring->count); i++) {
tx_desc = IXGBE_TX_DESC(tx_ring, i); tx_desc = IXGBE_TX_DESC(ring, i);
tx_buffer = &tx_ring->tx_buffer_info[i]; tx_buffer = &ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc; u0 = (struct my_u0 *)tx_desc;
if (dma_unmap_len(tx_buffer, len) > 0) { if (dma_unmap_len(tx_buffer, len) > 0) {
const char *ring_desc; const char *ring_desc;
if (i == tx_ring->next_to_use && if (i == ring->next_to_use &&
i == tx_ring->next_to_clean) i == ring->next_to_clean)
ring_desc = " NTC/U"; ring_desc = " NTC/U";
else if (i == tx_ring->next_to_use) else if (i == ring->next_to_use)
ring_desc = " NTU"; ring_desc = " NTU";
else if (i == tx_ring->next_to_clean) else if (i == ring->next_to_clean)
ring_desc = " NTC"; ring_desc = " NTC";
else else
ring_desc = ""; ring_desc = "";
...@@ -981,6 +998,10 @@ static void ixgbe_update_xoff_rx_lfc(struct ixgbe_adapter *adapter) ...@@ -981,6 +998,10 @@ static void ixgbe_update_xoff_rx_lfc(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
clear_bit(__IXGBE_HANG_CHECK_ARMED, clear_bit(__IXGBE_HANG_CHECK_ARMED,
&adapter->tx_ring[i]->state); &adapter->tx_ring[i]->state);
for (i = 0; i < adapter->num_xdp_queues; i++)
clear_bit(__IXGBE_HANG_CHECK_ARMED,
&adapter->xdp_ring[i]->state);
} }
static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
...@@ -1025,6 +1046,14 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) ...@@ -1025,6 +1046,14 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
if (xoff[tc]) if (xoff[tc])
clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state); clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
struct ixgbe_ring *xdp_ring = adapter->xdp_ring[i];
tc = xdp_ring->dcb_tc;
if (xoff[tc])
clear_bit(__IXGBE_HANG_CHECK_ARMED, &xdp_ring->state);
}
} }
static u64 ixgbe_get_tx_completed(struct ixgbe_ring *ring) static u64 ixgbe_get_tx_completed(struct ixgbe_ring *ring)
...@@ -1176,7 +1205,10 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -1176,7 +1205,10 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
total_packets += tx_buffer->gso_segs; total_packets += tx_buffer->gso_segs;
/* free the skb */ /* free the skb */
napi_consume_skb(tx_buffer->skb, napi_budget); if (ring_is_xdp(tx_ring))
page_frag_free(tx_buffer->data);
else
napi_consume_skb(tx_buffer->skb, napi_budget);
/* unmap skb header data */ /* unmap skb header data */
dma_unmap_single(tx_ring->dev, dma_unmap_single(tx_ring->dev,
...@@ -1237,7 +1269,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -1237,7 +1269,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) { if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
/* schedule immediate reset if we believe we hung */ /* schedule immediate reset if we believe we hung */
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
e_err(drv, "Detected Tx Unit Hang\n" e_err(drv, "Detected Tx Unit Hang %s\n"
" Tx Queue <%d>\n" " Tx Queue <%d>\n"
" TDH, TDT <%x>, <%x>\n" " TDH, TDT <%x>, <%x>\n"
" next_to_use <%x>\n" " next_to_use <%x>\n"
...@@ -1245,13 +1277,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -1245,13 +1277,16 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
"tx_buffer_info[next_to_clean]\n" "tx_buffer_info[next_to_clean]\n"
" time_stamp <%lx>\n" " time_stamp <%lx>\n"
" jiffies <%lx>\n", " jiffies <%lx>\n",
ring_is_xdp(tx_ring) ? "(XDP)" : "",
tx_ring->queue_index, tx_ring->queue_index,
IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)), IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)),
IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)), IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)),
tx_ring->next_to_use, i, tx_ring->next_to_use, i,
tx_ring->tx_buffer_info[i].time_stamp, jiffies); tx_ring->tx_buffer_info[i].time_stamp, jiffies);
netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); if (!ring_is_xdp(tx_ring))
netif_stop_subqueue(tx_ring->netdev,
tx_ring->queue_index);
e_info(probe, e_info(probe,
"tx hang %d detected on queue %d, resetting adapter\n", "tx hang %d detected on queue %d, resetting adapter\n",
...@@ -1264,6 +1299,9 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -1264,6 +1299,9 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
return true; return true;
} }
if (ring_is_xdp(tx_ring))
return !!budget;
netdev_tx_completed_queue(txring_txq(tx_ring), netdev_tx_completed_queue(txring_txq(tx_ring),
total_packets, total_bytes); total_packets, total_bytes);
...@@ -1855,6 +1893,10 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring, ...@@ -1855,6 +1893,10 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring,
* @rx_desc: pointer to the EOP Rx descriptor * @rx_desc: pointer to the EOP Rx descriptor
* @skb: pointer to current skb being fixed * @skb: pointer to current skb being fixed
* *
* Check if the skb is valid in the XDP case it will be an error pointer.
* Return true in this case to abort processing and advance to next
* descriptor.
*
* Check for corrupted packet headers caused by senders on the local L2 * Check for corrupted packet headers caused by senders on the local L2
* embedded NIC switch not setting up their Tx Descriptors right. These * embedded NIC switch not setting up their Tx Descriptors right. These
* should be very rare. * should be very rare.
...@@ -1873,6 +1915,10 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring, ...@@ -1873,6 +1915,10 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
{ {
struct net_device *netdev = rx_ring->netdev; struct net_device *netdev = rx_ring->netdev;
/* XDP packets use error pointer so abort at this point */
if (IS_ERR(skb))
return true;
/* verify that the packet does not have any known errors */ /* verify that the packet does not have any known errors */
if (unlikely(ixgbe_test_staterr(rx_desc, if (unlikely(ixgbe_test_staterr(rx_desc,
IXGBE_RXDADV_ERR_FRAME_ERR_MASK) && IXGBE_RXDADV_ERR_FRAME_ERR_MASK) &&
...@@ -2048,7 +2094,7 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring, ...@@ -2048,7 +2094,7 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring,
/* hand second half of page back to the ring */ /* hand second half of page back to the ring */
ixgbe_reuse_rx_page(rx_ring, rx_buffer); ixgbe_reuse_rx_page(rx_ring, rx_buffer);
} else { } else {
if (IXGBE_CB(skb)->dma == rx_buffer->dma) { if (!IS_ERR(skb) && IXGBE_CB(skb)->dma == rx_buffer->dma) {
/* the page has been released from the ring */ /* the page has been released from the ring */
IXGBE_CB(skb)->page_released = true; IXGBE_CB(skb)->page_released = true;
} else { } else {
...@@ -2069,21 +2115,22 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring, ...@@ -2069,21 +2115,22 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring,
static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring, static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,
struct ixgbe_rx_buffer *rx_buffer, struct ixgbe_rx_buffer *rx_buffer,
union ixgbe_adv_rx_desc *rx_desc, struct xdp_buff *xdp,
unsigned int size) union ixgbe_adv_rx_desc *rx_desc)
{ {
void *va = page_address(rx_buffer->page) + rx_buffer->page_offset; unsigned int size = xdp->data_end - xdp->data;
#if (PAGE_SIZE < 8192) #if (PAGE_SIZE < 8192)
unsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2; unsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2;
#else #else
unsigned int truesize = SKB_DATA_ALIGN(size); unsigned int truesize = SKB_DATA_ALIGN(xdp->data_end -
xdp->data_hard_start);
#endif #endif
struct sk_buff *skb; struct sk_buff *skb;
/* prefetch first cache line of first page */ /* prefetch first cache line of first page */
prefetch(va); prefetch(xdp->data);
#if L1_CACHE_BYTES < 128 #if L1_CACHE_BYTES < 128
prefetch(va + L1_CACHE_BYTES); prefetch(xdp->data + L1_CACHE_BYTES);
#endif #endif
/* allocate a skb to store the frags */ /* allocate a skb to store the frags */
...@@ -2096,7 +2143,7 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring, ...@@ -2096,7 +2143,7 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,
IXGBE_CB(skb)->dma = rx_buffer->dma; IXGBE_CB(skb)->dma = rx_buffer->dma;
skb_add_rx_frag(skb, 0, rx_buffer->page, skb_add_rx_frag(skb, 0, rx_buffer->page,
rx_buffer->page_offset, xdp->data - page_address(rx_buffer->page),
size, truesize); size, truesize);
#if (PAGE_SIZE < 8192) #if (PAGE_SIZE < 8192)
rx_buffer->page_offset ^= truesize; rx_buffer->page_offset ^= truesize;
...@@ -2104,7 +2151,8 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring, ...@@ -2104,7 +2151,8 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,
rx_buffer->page_offset += truesize; rx_buffer->page_offset += truesize;
#endif #endif
} else { } else {
memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); memcpy(__skb_put(skb, size),
xdp->data, ALIGN(size, sizeof(long)));
rx_buffer->pagecnt_bias++; rx_buffer->pagecnt_bias++;
} }
...@@ -2113,32 +2161,32 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring, ...@@ -2113,32 +2161,32 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,
static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring, static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,
struct ixgbe_rx_buffer *rx_buffer, struct ixgbe_rx_buffer *rx_buffer,
union ixgbe_adv_rx_desc *rx_desc, struct xdp_buff *xdp,
unsigned int size) union ixgbe_adv_rx_desc *rx_desc)
{ {
void *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
#if (PAGE_SIZE < 8192) #if (PAGE_SIZE < 8192)
unsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2; unsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2;
#else #else
unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
SKB_DATA_ALIGN(IXGBE_SKB_PAD + size); SKB_DATA_ALIGN(xdp->data_end -
xdp->data_hard_start);
#endif #endif
struct sk_buff *skb; struct sk_buff *skb;
/* prefetch first cache line of first page */ /* prefetch first cache line of first page */
prefetch(va); prefetch(xdp->data);
#if L1_CACHE_BYTES < 128 #if L1_CACHE_BYTES < 128
prefetch(va + L1_CACHE_BYTES); prefetch(xdp->data + L1_CACHE_BYTES);
#endif #endif
/* build an skb around the page buffer */ /* build an skb to around the page buffer */
skb = build_skb(va - IXGBE_SKB_PAD, truesize); skb = build_skb(xdp->data_hard_start, truesize);
if (unlikely(!skb)) if (unlikely(!skb))
return NULL; return NULL;
/* update pointers within the skb to store the data */ /* update pointers within the skb to store the data */
skb_reserve(skb, IXGBE_SKB_PAD); skb_reserve(skb, xdp->data - xdp->data_hard_start);
__skb_put(skb, size); __skb_put(skb, xdp->data_end - xdp->data);
/* record DMA address if this is the start of a chain of buffers */ /* record DMA address if this is the start of a chain of buffers */
if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP)) if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP))
...@@ -2154,6 +2202,65 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring, ...@@ -2154,6 +2202,65 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,
return skb; return skb;
} }
#define IXGBE_XDP_PASS 0
#define IXGBE_XDP_CONSUMED 1
#define IXGBE_XDP_TX 2
static int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter,
struct xdp_buff *xdp);
static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
struct ixgbe_ring *rx_ring,
struct xdp_buff *xdp)
{
int result = IXGBE_XDP_PASS;
struct bpf_prog *xdp_prog;
u32 act;
rcu_read_lock();
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
if (!xdp_prog)
goto xdp_out;
act = bpf_prog_run_xdp(xdp_prog, xdp);
switch (act) {
case XDP_PASS:
break;
case XDP_TX:
result = ixgbe_xmit_xdp_ring(adapter, xdp);
break;
default:
bpf_warn_invalid_xdp_action(act);
case XDP_ABORTED:
trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
/* fallthrough -- handle aborts by dropping packet */
case XDP_DROP:
result = IXGBE_XDP_CONSUMED;
break;
}
xdp_out:
rcu_read_unlock();
return ERR_PTR(-result);
}
static void ixgbe_rx_buffer_flip(struct ixgbe_ring *rx_ring,
struct ixgbe_rx_buffer *rx_buffer,
unsigned int size)
{
#if (PAGE_SIZE < 8192)
unsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2;
rx_buffer->page_offset ^= truesize;
#else
unsigned int truesize = ring_uses_build_skb(rx_ring) ?
SKB_DATA_ALIGN(IXGBE_SKB_PAD + size) :
SKB_DATA_ALIGN(size);
rx_buffer->page_offset += truesize;
#endif
}
/** /**
* ixgbe_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf * ixgbe_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
* @q_vector: structure containing interrupt and ring information * @q_vector: structure containing interrupt and ring information
...@@ -2172,17 +2279,19 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ...@@ -2172,17 +2279,19 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
const int budget) const int budget)
{ {
unsigned int total_rx_bytes = 0, total_rx_packets = 0; unsigned int total_rx_bytes = 0, total_rx_packets = 0;
#ifdef IXGBE_FCOE
struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_adapter *adapter = q_vector->adapter;
#ifdef IXGBE_FCOE
int ddp_bytes; int ddp_bytes;
unsigned int mss = 0; unsigned int mss = 0;
#endif /* IXGBE_FCOE */ #endif /* IXGBE_FCOE */
u16 cleaned_count = ixgbe_desc_unused(rx_ring); u16 cleaned_count = ixgbe_desc_unused(rx_ring);
bool xdp_xmit = false;
while (likely(total_rx_packets < budget)) { while (likely(total_rx_packets < budget)) {
union ixgbe_adv_rx_desc *rx_desc; union ixgbe_adv_rx_desc *rx_desc;
struct ixgbe_rx_buffer *rx_buffer; struct ixgbe_rx_buffer *rx_buffer;
struct sk_buff *skb; struct sk_buff *skb;
struct xdp_buff xdp;
unsigned int size; unsigned int size;
/* return some buffers to hardware, one at a time is too slow */ /* return some buffers to hardware, one at a time is too slow */
...@@ -2205,14 +2314,34 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ...@@ -2205,14 +2314,34 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size); rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size);
/* retrieve a buffer from the ring */ /* retrieve a buffer from the ring */
if (skb) if (!skb) {
xdp.data = page_address(rx_buffer->page) +
rx_buffer->page_offset;
xdp.data_hard_start = xdp.data -
ixgbe_rx_offset(rx_ring);
xdp.data_end = xdp.data + size;
skb = ixgbe_run_xdp(adapter, rx_ring, &xdp);
}
if (IS_ERR(skb)) {
if (PTR_ERR(skb) == -IXGBE_XDP_TX) {
xdp_xmit = true;
ixgbe_rx_buffer_flip(rx_ring, rx_buffer, size);
} else {
rx_buffer->pagecnt_bias++;
}
total_rx_packets++;
total_rx_bytes += size;
} else if (skb) {
ixgbe_add_rx_frag(rx_ring, rx_buffer, skb, size); ixgbe_add_rx_frag(rx_ring, rx_buffer, skb, size);
else if (ring_uses_build_skb(rx_ring)) } else if (ring_uses_build_skb(rx_ring)) {
skb = ixgbe_build_skb(rx_ring, rx_buffer, skb = ixgbe_build_skb(rx_ring, rx_buffer,
rx_desc, size); &xdp, rx_desc);
else } else {
skb = ixgbe_construct_skb(rx_ring, rx_buffer, skb = ixgbe_construct_skb(rx_ring, rx_buffer,
rx_desc, size); &xdp, rx_desc);
}
/* exit if we failed to retrieve a buffer */ /* exit if we failed to retrieve a buffer */
if (!skb) { if (!skb) {
...@@ -2269,6 +2398,16 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ...@@ -2269,6 +2398,16 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
total_rx_packets++; total_rx_packets++;
} }
if (xdp_xmit) {
struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()];
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch.
*/
wmb();
writel(ring->next_to_use, ring->tail);
}
u64_stats_update_begin(&rx_ring->syncp); u64_stats_update_begin(&rx_ring->syncp);
rx_ring->stats.packets += total_rx_packets; rx_ring->stats.packets += total_rx_packets;
rx_ring->stats.bytes += total_rx_bytes; rx_ring->stats.bytes += total_rx_bytes;
...@@ -3373,6 +3512,8 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) ...@@ -3373,6 +3512,8 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
/* Setup the HW Tx Head and Tail descriptor pointers */ /* Setup the HW Tx Head and Tail descriptor pointers */
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]); ixgbe_configure_tx_ring(adapter, adapter->tx_ring[i]);
for (i = 0; i < adapter->num_xdp_queues; i++)
ixgbe_configure_tx_ring(adapter, adapter->xdp_ring[i]);
} }
static void ixgbe_enable_rx_drop(struct ixgbe_adapter *adapter, static void ixgbe_enable_rx_drop(struct ixgbe_adapter *adapter,
...@@ -3497,6 +3638,28 @@ void ixgbe_store_key(struct ixgbe_adapter *adapter) ...@@ -3497,6 +3638,28 @@ void ixgbe_store_key(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), adapter->rss_key[i]); IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), adapter->rss_key[i]);
} }
/**
* ixgbe_init_rss_key - Initialize adapter RSS key
* @adapter: device handle
*
* Allocates and initializes the RSS key if it is not allocated.
**/
static inline int ixgbe_init_rss_key(struct ixgbe_adapter *adapter)
{
u32 *rss_key;
if (!adapter->rss_key) {
rss_key = kzalloc(IXGBE_RSS_KEY_SIZE, GFP_KERNEL);
if (unlikely(!rss_key))
return -ENOMEM;
netdev_rss_key_fill(rss_key, IXGBE_RSS_KEY_SIZE);
adapter->rss_key = rss_key;
}
return 0;
}
/** /**
* ixgbe_store_reta - Write the RETA table to HW * ixgbe_store_reta - Write the RETA table to HW
* @adapter: device handle * @adapter: device handle
...@@ -3599,7 +3762,7 @@ static void ixgbe_setup_vfreta(struct ixgbe_adapter *adapter) ...@@ -3599,7 +3762,7 @@ static void ixgbe_setup_vfreta(struct ixgbe_adapter *adapter)
/* Fill out hash function seeds */ /* Fill out hash function seeds */
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
IXGBE_WRITE_REG(hw, IXGBE_PFVFRSSRK(i, pf_pool), IXGBE_WRITE_REG(hw, IXGBE_PFVFRSSRK(i, pf_pool),
adapter->rss_key[i]); *(adapter->rss_key + i));
/* Fill out the redirection table */ /* Fill out the redirection table */
for (i = 0, j = 0; i < 64; i++, j++) { for (i = 0, j = 0; i < 64; i++, j++) {
...@@ -3660,7 +3823,6 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) ...@@ -3660,7 +3823,6 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; rss_field |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
netdev_rss_key_fill(adapter->rss_key, sizeof(adapter->rss_key));
if ((hw->mac.type >= ixgbe_mac_X550) && if ((hw->mac.type >= ixgbe_mac_X550) &&
(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) { (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) {
unsigned int pf_pool = adapter->num_vfs; unsigned int pf_pool = adapter->num_vfs;
...@@ -5514,7 +5676,10 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring) ...@@ -5514,7 +5676,10 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring)
union ixgbe_adv_tx_desc *eop_desc, *tx_desc; union ixgbe_adv_tx_desc *eop_desc, *tx_desc;
/* Free all the Tx ring sk_buffs */ /* Free all the Tx ring sk_buffs */
dev_kfree_skb_any(tx_buffer->skb); if (ring_is_xdp(tx_ring))
page_frag_free(tx_buffer->data);
else
dev_kfree_skb_any(tx_buffer->skb);
/* unmap skb header data */ /* unmap skb header data */
dma_unmap_single(tx_ring->dev, dma_unmap_single(tx_ring->dev,
...@@ -5555,7 +5720,8 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring) ...@@ -5555,7 +5720,8 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring)
} }
/* reset BQL for queue */ /* reset BQL for queue */
netdev_tx_reset_queue(txring_txq(tx_ring)); if (!ring_is_xdp(tx_ring))
netdev_tx_reset_queue(txring_txq(tx_ring));
/* reset next_to_use and next_to_clean */ /* reset next_to_use and next_to_clean */
tx_ring->next_to_use = 0; tx_ring->next_to_use = 0;
...@@ -5584,6 +5750,8 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter) ...@@ -5584,6 +5750,8 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
ixgbe_clean_tx_ring(adapter->tx_ring[i]); ixgbe_clean_tx_ring(adapter->tx_ring[i]);
for (i = 0; i < adapter->num_xdp_queues; i++)
ixgbe_clean_tx_ring(adapter->xdp_ring[i]);
} }
static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter) static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
...@@ -5678,6 +5846,11 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ...@@ -5678,6 +5846,11 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
u8 reg_idx = adapter->tx_ring[i]->reg_idx; u8 reg_idx = adapter->tx_ring[i]->reg_idx;
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH); IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
u8 reg_idx = adapter->xdp_ring[i]->reg_idx;
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
}
/* Disable the Tx DMA engine on 82599 and later MAC */ /* Disable the Tx DMA engine on 82599 and later MAC */
switch (hw->mac.type) { switch (hw->mac.type) {
...@@ -5863,6 +6036,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter, ...@@ -5863,6 +6036,9 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
if (!adapter->mac_table) if (!adapter->mac_table)
return -ENOMEM; return -ENOMEM;
if (ixgbe_init_rss_key(adapter))
return -ENOMEM;
/* Set MAC specific capability flags and exceptions */ /* Set MAC specific capability flags and exceptions */
switch (hw->mac.type) { switch (hw->mac.type) {
case ixgbe_mac_82598EB: case ixgbe_mac_82598EB:
...@@ -6048,7 +6224,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring) ...@@ -6048,7 +6224,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
**/ **/
static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
{ {
int i, err = 0; int i, j = 0, err = 0;
for (i = 0; i < adapter->num_tx_queues; i++) { for (i = 0; i < adapter->num_tx_queues; i++) {
err = ixgbe_setup_tx_resources(adapter->tx_ring[i]); err = ixgbe_setup_tx_resources(adapter->tx_ring[i]);
...@@ -6058,10 +6234,20 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) ...@@ -6058,10 +6234,20 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
e_err(probe, "Allocation for Tx Queue %u failed\n", i); e_err(probe, "Allocation for Tx Queue %u failed\n", i);
goto err_setup_tx; goto err_setup_tx;
} }
for (j = 0; j < adapter->num_xdp_queues; j++) {
err = ixgbe_setup_tx_resources(adapter->xdp_ring[j]);
if (!err)
continue;
e_err(probe, "Allocation for Tx Queue %u failed\n", j);
goto err_setup_tx;
}
return 0; return 0;
err_setup_tx: err_setup_tx:
/* rewind the index freeing the rings as we go */ /* rewind the index freeing the rings as we go */
while (j--)
ixgbe_free_tx_resources(adapter->xdp_ring[j]);
while (i--) while (i--)
ixgbe_free_tx_resources(adapter->tx_ring[i]); ixgbe_free_tx_resources(adapter->tx_ring[i]);
return err; return err;
...@@ -6073,7 +6259,8 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) ...@@ -6073,7 +6259,8 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
* *
* Returns 0 on success, negative on failure * Returns 0 on success, negative on failure
**/ **/
int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring) int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
struct ixgbe_ring *rx_ring)
{ {
struct device *dev = rx_ring->dev; struct device *dev = rx_ring->dev;
int orig_node = dev_to_node(dev); int orig_node = dev_to_node(dev);
...@@ -6112,6 +6299,8 @@ int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring) ...@@ -6112,6 +6299,8 @@ int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring)
rx_ring->next_to_clean = 0; rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0; rx_ring->next_to_use = 0;
rx_ring->xdp_prog = adapter->xdp_prog;
return 0; return 0;
err: err:
vfree(rx_ring->rx_buffer_info); vfree(rx_ring->rx_buffer_info);
...@@ -6135,7 +6324,7 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) ...@@ -6135,7 +6324,7 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)
int i, err = 0; int i, err = 0;
for (i = 0; i < adapter->num_rx_queues; i++) { for (i = 0; i < adapter->num_rx_queues; i++) {
err = ixgbe_setup_rx_resources(adapter->rx_ring[i]); err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]);
if (!err) if (!err)
continue; continue;
...@@ -6191,6 +6380,9 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) ...@@ -6191,6 +6380,9 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
if (adapter->tx_ring[i]->desc) if (adapter->tx_ring[i]->desc)
ixgbe_free_tx_resources(adapter->tx_ring[i]); ixgbe_free_tx_resources(adapter->tx_ring[i]);
for (i = 0; i < adapter->num_xdp_queues; i++)
if (adapter->xdp_ring[i]->desc)
ixgbe_free_tx_resources(adapter->xdp_ring[i]);
} }
/** /**
...@@ -6203,6 +6395,7 @@ void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring) ...@@ -6203,6 +6395,7 @@ void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring)
{ {
ixgbe_clean_rx_ring(rx_ring); ixgbe_clean_rx_ring(rx_ring);
rx_ring->xdp_prog = NULL;
vfree(rx_ring->rx_buffer_info); vfree(rx_ring->rx_buffer_info);
rx_ring->rx_buffer_info = NULL; rx_ring->rx_buffer_info = NULL;
...@@ -6609,6 +6802,14 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) ...@@ -6609,6 +6802,14 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
bytes += tx_ring->stats.bytes; bytes += tx_ring->stats.bytes;
packets += tx_ring->stats.packets; packets += tx_ring->stats.packets;
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
struct ixgbe_ring *xdp_ring = adapter->xdp_ring[i];
restart_queue += xdp_ring->tx_stats.restart_queue;
tx_busy += xdp_ring->tx_stats.tx_busy;
bytes += xdp_ring->stats.bytes;
packets += xdp_ring->stats.packets;
}
adapter->restart_queue = restart_queue; adapter->restart_queue = restart_queue;
adapter->tx_busy = tx_busy; adapter->tx_busy = tx_busy;
netdev->stats.tx_bytes = bytes; netdev->stats.tx_bytes = bytes;
...@@ -6802,6 +7003,9 @@ static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter) ...@@ -6802,6 +7003,9 @@ static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
set_bit(__IXGBE_TX_FDIR_INIT_DONE, set_bit(__IXGBE_TX_FDIR_INIT_DONE,
&(adapter->tx_ring[i]->state)); &(adapter->tx_ring[i]->state));
for (i = 0; i < adapter->num_xdp_queues; i++)
set_bit(__IXGBE_TX_FDIR_INIT_DONE,
&adapter->xdp_ring[i]->state);
/* re-enable flow director interrupts */ /* re-enable flow director interrupts */
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR); IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
} else { } else {
...@@ -6835,6 +7039,8 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter) ...@@ -6835,6 +7039,8 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter)
if (netif_carrier_ok(adapter->netdev)) { if (netif_carrier_ok(adapter->netdev)) {
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
set_check_for_tx_hang(adapter->tx_ring[i]); set_check_for_tx_hang(adapter->tx_ring[i]);
for (i = 0; i < adapter->num_xdp_queues; i++)
set_check_for_tx_hang(adapter->xdp_ring[i]);
} }
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
...@@ -7065,6 +7271,13 @@ static bool ixgbe_ring_tx_pending(struct ixgbe_adapter *adapter) ...@@ -7065,6 +7271,13 @@ static bool ixgbe_ring_tx_pending(struct ixgbe_adapter *adapter)
return true; return true;
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
struct ixgbe_ring *ring = adapter->xdp_ring[i];
if (ring->next_to_use != ring->next_to_clean)
return true;
}
return false; return false;
} }
...@@ -8022,6 +8235,62 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb, ...@@ -8022,6 +8235,62 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
#endif #endif
} }
static int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter,
struct xdp_buff *xdp)
{
struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()];
struct ixgbe_tx_buffer *tx_buffer;
union ixgbe_adv_tx_desc *tx_desc;
u32 len, cmd_type;
dma_addr_t dma;
u16 i;
len = xdp->data_end - xdp->data;
if (unlikely(!ixgbe_desc_unused(ring)))
return IXGBE_XDP_CONSUMED;
dma = dma_map_single(ring->dev, xdp->data, len, DMA_TO_DEVICE);
if (dma_mapping_error(ring->dev, dma))
return IXGBE_XDP_CONSUMED;
/* record the location of the first descriptor for this packet */
tx_buffer = &ring->tx_buffer_info[ring->next_to_use];
tx_buffer->bytecount = len;
tx_buffer->gso_segs = 1;
tx_buffer->protocol = 0;
i = ring->next_to_use;
tx_desc = IXGBE_TX_DESC(ring, i);
dma_unmap_len_set(tx_buffer, len, len);
dma_unmap_addr_set(tx_buffer, dma, dma);
tx_buffer->data = xdp->data;
tx_desc->read.buffer_addr = cpu_to_le64(dma);
/* put descriptor type bits */
cmd_type = IXGBE_ADVTXD_DTYP_DATA |
IXGBE_ADVTXD_DCMD_DEXT |
IXGBE_ADVTXD_DCMD_IFCS;
cmd_type |= len | IXGBE_TXD_CMD;
tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
tx_desc->read.olinfo_status =
cpu_to_le32(len << IXGBE_ADVTXD_PAYLEN_SHIFT);
/* Avoid any potential race with xdp_xmit and cleanup */
smp_wmb();
/* set next_to_watch value indicating a packet is present */
i++;
if (i == ring->count)
i = 0;
tx_buffer->next_to_watch = tx_desc;
ring->next_to_use = i;
return IXGBE_XDP_TX;
}
netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb, netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
struct ixgbe_adapter *adapter, struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring) struct ixgbe_ring *tx_ring)
...@@ -8313,6 +8582,23 @@ static void ixgbe_netpoll(struct net_device *netdev) ...@@ -8313,6 +8582,23 @@ static void ixgbe_netpoll(struct net_device *netdev)
#endif #endif
static void ixgbe_get_ring_stats64(struct rtnl_link_stats64 *stats,
struct ixgbe_ring *ring)
{
u64 bytes, packets;
unsigned int start;
if (ring) {
do {
start = u64_stats_fetch_begin_irq(&ring->syncp);
packets = ring->stats.packets;
bytes = ring->stats.bytes;
} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
stats->tx_packets += packets;
stats->tx_bytes += bytes;
}
}
static void ixgbe_get_stats64(struct net_device *netdev, static void ixgbe_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats) struct rtnl_link_stats64 *stats)
{ {
...@@ -8338,18 +8624,13 @@ static void ixgbe_get_stats64(struct net_device *netdev, ...@@ -8338,18 +8624,13 @@ static void ixgbe_get_stats64(struct net_device *netdev,
for (i = 0; i < adapter->num_tx_queues; i++) { for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *ring = ACCESS_ONCE(adapter->tx_ring[i]); struct ixgbe_ring *ring = ACCESS_ONCE(adapter->tx_ring[i]);
u64 bytes, packets;
unsigned int start;
if (ring) { ixgbe_get_ring_stats64(stats, ring);
do { }
start = u64_stats_fetch_begin_irq(&ring->syncp); for (i = 0; i < adapter->num_xdp_queues; i++) {
packets = ring->stats.packets; struct ixgbe_ring *ring = ACCESS_ONCE(adapter->xdp_ring[i]);
bytes = ring->stats.bytes;
} while (u64_stats_fetch_retry_irq(&ring->syncp, start)); ixgbe_get_ring_stats64(stats, ring);
stats->tx_packets += packets;
stats->tx_bytes += bytes;
}
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -9468,6 +9749,68 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev, ...@@ -9468,6 +9749,68 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
return features; return features;
} }
static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
{
int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct bpf_prog *old_prog;
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
return -EINVAL;
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
return -EINVAL;
/* verify ixgbe ring attributes are sufficient for XDP */
for (i = 0; i < adapter->num_rx_queues; i++) {
struct ixgbe_ring *ring = adapter->rx_ring[i];
if (ring_is_rsc_enabled(ring))
return -EINVAL;
if (frame_size > ixgbe_rx_bufsz(ring))
return -EINVAL;
}
if (nr_cpu_ids > MAX_XDP_QUEUES)
return -ENOMEM;
old_prog = xchg(&adapter->xdp_prog, prog);
/* If transitioning XDP modes reconfigure rings */
if (!!prog != !!old_prog) {
int err = ixgbe_setup_tc(dev, netdev_get_num_tc(dev));
if (err) {
rcu_assign_pointer(adapter->xdp_prog, old_prog);
return -EINVAL;
}
} else {
for (i = 0; i < adapter->num_rx_queues; i++)
xchg(&adapter->rx_ring[i]->xdp_prog, adapter->xdp_prog);
}
if (old_prog)
bpf_prog_put(old_prog);
return 0;
}
static int ixgbe_xdp(struct net_device *dev, struct netdev_xdp *xdp)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
switch (xdp->command) {
case XDP_SETUP_PROG:
return ixgbe_xdp_setup(dev, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = !!(adapter->xdp_prog);
return 0;
default:
return -EINVAL;
}
}
static const struct net_device_ops ixgbe_netdev_ops = { static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open, .ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close, .ndo_stop = ixgbe_close,
...@@ -9513,6 +9856,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { ...@@ -9513,6 +9856,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_udp_tunnel_add = ixgbe_add_udp_tunnel_port, .ndo_udp_tunnel_add = ixgbe_add_udp_tunnel_port,
.ndo_udp_tunnel_del = ixgbe_del_udp_tunnel_port, .ndo_udp_tunnel_del = ixgbe_del_udp_tunnel_port,
.ndo_features_check = ixgbe_features_check, .ndo_features_check = ixgbe_features_check,
.ndo_xdp = ixgbe_xdp,
}; };
/** /**
...@@ -9943,6 +10287,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -9943,6 +10287,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) if (err)
goto err_sw_init; goto err_sw_init;
for (i = 0; i < adapter->num_xdp_queues; i++)
u64_stats_init(&adapter->xdp_ring[i]->syncp);
/* WOL not supported for all devices */ /* WOL not supported for all devices */
adapter->wol = 0; adapter->wol = 0;
hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap); hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap);
...@@ -10068,6 +10415,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -10068,6 +10415,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iounmap(adapter->io_addr); iounmap(adapter->io_addr);
kfree(adapter->jump_tables[0]); kfree(adapter->jump_tables[0]);
kfree(adapter->mac_table); kfree(adapter->mac_table);
kfree(adapter->rss_key);
err_ioremap: err_ioremap:
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
free_netdev(netdev); free_netdev(netdev);
...@@ -10152,6 +10500,7 @@ static void ixgbe_remove(struct pci_dev *pdev) ...@@ -10152,6 +10500,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
} }
kfree(adapter->mac_table); kfree(adapter->mac_table);
kfree(adapter->rss_key);
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
free_netdev(netdev); free_netdev(netdev);
......
...@@ -677,58 +677,6 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf) ...@@ -677,58 +677,6 @@ static void ixgbe_clear_vf_vlans(struct ixgbe_adapter *adapter, u32 vf)
} }
} }
static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
u8 num_tcs = netdev_get_num_tc(adapter->netdev);
/* remove VLAN filters beloning to this VF */
ixgbe_clear_vf_vlans(adapter, vf);
/* add back PF assigned VLAN or VLAN 0 */
ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf);
/* reset offloads to defaults */
ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan);
/* set outgoing tags for VFs */
if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) {
ixgbe_clear_vmvir(adapter, vf);
} else {
if (vfinfo->pf_qos || !num_tcs)
ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
vfinfo->pf_qos, vf);
else
ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
adapter->default_up, vf);
if (vfinfo->spoofchk_enabled)
hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
}
/* reset multicast table array for vf */
adapter->vfinfo[vf].num_vf_mc_hashes = 0;
/* Flush and reset the mta with the new values */
ixgbe_set_rx_mode(adapter->netdev);
ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
/* reset VF api back to unknown */
adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10;
}
static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
int vf, unsigned char *mac_addr)
{
ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, ETH_ALEN);
ixgbe_add_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
return 0;
}
static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
int vf, int index, unsigned char *mac_addr) int vf, int index, unsigned char *mac_addr)
{ {
...@@ -784,6 +732,59 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, ...@@ -784,6 +732,59 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter,
return 0; return 0;
} }
static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
{
struct ixgbe_hw *hw = &adapter->hw;
struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
u8 num_tcs = netdev_get_num_tc(adapter->netdev);
/* remove VLAN filters beloning to this VF */
ixgbe_clear_vf_vlans(adapter, vf);
/* add back PF assigned VLAN or VLAN 0 */
ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf);
/* reset offloads to defaults */
ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan);
/* set outgoing tags for VFs */
if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) {
ixgbe_clear_vmvir(adapter, vf);
} else {
if (vfinfo->pf_qos || !num_tcs)
ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
vfinfo->pf_qos, vf);
else
ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
adapter->default_up, vf);
if (vfinfo->spoofchk_enabled)
hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
}
/* reset multicast table array for vf */
adapter->vfinfo[vf].num_vf_mc_hashes = 0;
/* Flush and reset the mta with the new values */
ixgbe_set_rx_mode(adapter->netdev);
ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
ixgbe_set_vf_macvlan(adapter, vf, 0, NULL);
/* reset VF api back to unknown */
adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10;
}
static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
int vf, unsigned char *mac_addr)
{
ixgbe_del_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, ETH_ALEN);
ixgbe_add_mac_filter(adapter, adapter->vfinfo[vf].vf_mac_addresses, vf);
return 0;
}
int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
{ {
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev); struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
...@@ -1112,7 +1113,7 @@ static int ixgbe_get_vf_rss_key(struct ixgbe_adapter *adapter, ...@@ -1112,7 +1113,7 @@ static int ixgbe_get_vf_rss_key(struct ixgbe_adapter *adapter,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
memcpy(rss_key, adapter->rss_key, sizeof(adapter->rss_key)); memcpy(rss_key, adapter->rss_key, IXGBE_RSS_KEY_SIZE);
return 0; return 0;
} }
...@@ -1346,18 +1347,26 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter) ...@@ -1346,18 +1347,26 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter)
int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
if (!is_valid_ether_addr(mac) || (vf >= adapter->num_vfs))
if (vf >= adapter->num_vfs)
return -EINVAL;
if (is_zero_ether_addr(mac)) {
adapter->vfinfo[vf].pf_set_mac = false;
dev_info(&adapter->pdev->dev, "removing MAC on VF %d\n", vf);
} else if (is_valid_ether_addr(mac)) {
adapter->vfinfo[vf].pf_set_mac = true;
dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n",
mac, vf);
dev_info(&adapter->pdev->dev, "Reload the VF driver to make this change effective.");
if (test_bit(__IXGBE_DOWN, &adapter->state)) {
dev_warn(&adapter->pdev->dev, "The VF MAC address has been set, but the PF device is not up.\n");
dev_warn(&adapter->pdev->dev, "Bring the PF device up before attempting to use the VF device.\n");
}
} else {
return -EINVAL; return -EINVAL;
adapter->vfinfo[vf].pf_set_mac = true;
dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf);
dev_info(&adapter->pdev->dev, "Reload the VF driver to make this"
" change effective.");
if (test_bit(__IXGBE_DOWN, &adapter->state)) {
dev_warn(&adapter->pdev->dev, "The VF MAC address has been set,"
" but the PF device is not up.\n");
dev_warn(&adapter->pdev->dev, "Bring the PF device up before"
" attempting to use the VF device.\n");
} }
return ixgbe_set_vf_mac(adapter, vf, mac); return ixgbe_set_vf_mac(adapter, vf, mac);
} }
......
...@@ -3128,6 +3128,7 @@ enum ixgbe_phy_type { ...@@ -3128,6 +3128,7 @@ enum ixgbe_phy_type {
ixgbe_phy_x550em_kx4, ixgbe_phy_x550em_kx4,
ixgbe_phy_x550em_xfi, ixgbe_phy_x550em_xfi,
ixgbe_phy_x550em_ext_t, ixgbe_phy_x550em_ext_t,
ixgbe_phy_ext_1g_t,
ixgbe_phy_cu_unknown, ixgbe_phy_cu_unknown,
ixgbe_phy_qt, ixgbe_phy_qt,
ixgbe_phy_xaui, ixgbe_phy_xaui,
......
...@@ -95,6 +95,7 @@ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) ...@@ -95,6 +95,7 @@ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
{ {
s32 status; s32 status;
u32 ctrl, i; u32 ctrl, i;
u32 swfw_mask = hw->phy.phy_semaphore_mask;
/* Call adapter stop to disable tx/rx and clear interrupts */ /* Call adapter stop to disable tx/rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw); status = hw->mac.ops.stop_adapter(hw);
...@@ -105,10 +106,17 @@ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) ...@@ -105,10 +106,17 @@ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
ixgbe_clear_tx_pending(hw); ixgbe_clear_tx_pending(hw);
mac_reset_top: mac_reset_top:
status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
if (status) {
hw_dbg(hw, "semaphore failed with %d", status);
return IXGBE_ERR_SWFW_SYNC;
}
ctrl = IXGBE_CTRL_RST; ctrl = IXGBE_CTRL_RST;
ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_FLUSH(hw);
hw->mac.ops.release_swfw_sync(hw, swfw_mask);
usleep_range(1000, 1200); usleep_range(1000, 1200);
/* Poll for reset bit to self-clear indicating reset is complete */ /* Poll for reset bit to self-clear indicating reset is complete */
......
...@@ -49,6 +49,18 @@ static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) ...@@ -49,6 +49,18 @@ static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
return 0; return 0;
} }
static s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw)
{
struct ixgbe_phy_info *phy = &hw->phy;
/* Start with X540 invariants, since so similar */
ixgbe_get_invariants_X540(hw);
phy->ops.set_phy_power = NULL;
return 0;
}
static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)
{ {
struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_mac_info *mac = &hw->mac;
...@@ -334,9 +346,11 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) ...@@ -334,9 +346,11 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
else else
hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
/* Fallthrough */ /* Fallthrough */
case IXGBE_DEV_ID_X550EM_X_1G_T:
case IXGBE_DEV_ID_X550EM_X_10G_T: case IXGBE_DEV_ID_X550EM_X_10G_T:
return ixgbe_identify_phy_generic(hw); return ixgbe_identify_phy_generic(hw);
case IXGBE_DEV_ID_X550EM_X_1G_T:
hw->phy.type = ixgbe_phy_ext_1g_t;
break;
case IXGBE_DEV_ID_X550EM_A_1G_T: case IXGBE_DEV_ID_X550EM_A_1G_T:
case IXGBE_DEV_ID_X550EM_A_1G_T_L: case IXGBE_DEV_ID_X550EM_A_1G_T_L:
hw->phy.type = ixgbe_phy_fw; hw->phy.type = ixgbe_phy_fw;
...@@ -2158,6 +2172,8 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) ...@@ -2158,6 +2172,8 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
ixgbe_set_soft_rate_select_speed; ixgbe_set_soft_rate_select_speed;
break; break;
case ixgbe_media_type_copper: case ixgbe_media_type_copper:
if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T)
break;
mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
mac->ops.setup_fc = ixgbe_setup_fc_generic; mac->ops.setup_fc = ixgbe_setup_fc_generic;
mac->ops.check_link = ixgbe_check_link_t_X550em; mac->ops.check_link = ixgbe_check_link_t_X550em;
...@@ -2238,6 +2254,7 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, ...@@ -2238,6 +2254,7 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
*speed = IXGBE_LINK_SPEED_1GB_FULL | *speed = IXGBE_LINK_SPEED_1GB_FULL |
IXGBE_LINK_SPEED_10GB_FULL; IXGBE_LINK_SPEED_10GB_FULL;
break; break;
case ixgbe_phy_ext_1g_t:
case ixgbe_phy_sgmii: case ixgbe_phy_sgmii:
*speed = IXGBE_LINK_SPEED_1GB_FULL; *speed = IXGBE_LINK_SPEED_1GB_FULL;
break; break;
...@@ -3185,6 +3202,11 @@ static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) ...@@ -3185,6 +3202,11 @@ static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
phy->ops.setup_link = ixgbe_setup_fw_link; phy->ops.setup_link = ixgbe_setup_fw_link;
phy->ops.reset = ixgbe_reset_phy_fw; phy->ops.reset = ixgbe_reset_phy_fw;
break; break;
case ixgbe_phy_ext_1g_t:
phy->ops.setup_link = NULL;
phy->ops.read_reg = NULL;
phy->ops.write_reg = NULL;
break;
default: default:
break; break;
} }
...@@ -3318,6 +3340,7 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) ...@@ -3318,6 +3340,7 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
u32 ctrl = 0; u32 ctrl = 0;
u32 i; u32 i;
bool link_up = false; bool link_up = false;
u32 swfw_mask = hw->phy.phy_semaphore_mask;
/* Call adapter stop to disable Tx/Rx and clear interrupts */ /* Call adapter stop to disable Tx/Rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw); status = hw->mac.ops.stop_adapter(hw);
...@@ -3363,9 +3386,16 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) ...@@ -3363,9 +3386,16 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
ctrl = IXGBE_CTRL_RST; ctrl = IXGBE_CTRL_RST;
} }
status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
if (status) {
hw_dbg(hw, "semaphore failed with %d", status);
return IXGBE_ERR_SWFW_SYNC;
}
ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_FLUSH(hw);
hw->mac.ops.release_swfw_sync(hw, swfw_mask);
usleep_range(1000, 1200); usleep_range(1000, 1200);
/* Poll for reset bit to self-clear meaning reset is complete */ /* Poll for reset bit to self-clear meaning reset is complete */
...@@ -3880,6 +3910,17 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = { ...@@ -3880,6 +3910,17 @@ static const struct ixgbe_phy_operations phy_ops_X550EM_x = {
.write_reg = &ixgbe_write_phy_reg_generic, .write_reg = &ixgbe_write_phy_reg_generic,
}; };
static const struct ixgbe_phy_operations phy_ops_x550em_x_fw = {
X550_COMMON_PHY
.check_overtemp = NULL,
.init = ixgbe_init_phy_ops_X550em,
.identify = ixgbe_identify_phy_x550em,
.read_reg = NULL,
.write_reg = NULL,
.read_reg_mdi = NULL,
.write_reg_mdi = NULL,
};
static const struct ixgbe_phy_operations phy_ops_x550em_a = { static const struct ixgbe_phy_operations phy_ops_x550em_a = {
X550_COMMON_PHY X550_COMMON_PHY
.check_overtemp = &ixgbe_tn_check_overtemp, .check_overtemp = &ixgbe_tn_check_overtemp,
...@@ -3942,6 +3983,16 @@ const struct ixgbe_info ixgbe_X550EM_x_info = { ...@@ -3942,6 +3983,16 @@ const struct ixgbe_info ixgbe_X550EM_x_info = {
.link_ops = &link_ops_x550em_x, .link_ops = &link_ops_x550em_x,
}; };
const struct ixgbe_info ixgbe_x550em_x_fw_info = {
.mac = ixgbe_mac_X550EM_x,
.get_invariants = ixgbe_get_invariants_X550_x_fw,
.mac_ops = &mac_ops_X550EM_x,
.eeprom_ops = &eeprom_ops_X550EM_x,
.phy_ops = &phy_ops_x550em_x_fw,
.mbx_ops = &mbx_ops_generic,
.mvals = ixgbe_mvals_X550EM_x,
};
const struct ixgbe_info ixgbe_x550em_a_info = { const struct ixgbe_info ixgbe_x550em_a_info = {
.mac = ixgbe_mac_x550em_a, .mac = ixgbe_mac_x550em_a,
.get_invariants = &ixgbe_get_invariants_X550_a, .get_invariants = &ixgbe_get_invariants_X550_a,
......
...@@ -80,7 +80,7 @@ static struct ixgbe_stats ixgbevf_gstrings_stats[] = { ...@@ -80,7 +80,7 @@ static struct ixgbe_stats ixgbevf_gstrings_stats[] = {
#define IXGBEVF_QUEUE_STATS_LEN ( \ #define IXGBEVF_QUEUE_STATS_LEN ( \
(((struct ixgbevf_adapter *)netdev_priv(netdev))->num_tx_queues + \ (((struct ixgbevf_adapter *)netdev_priv(netdev))->num_tx_queues + \
((struct ixgbevf_adapter *)netdev_priv(netdev))->num_rx_queues) * \ ((struct ixgbevf_adapter *)netdev_priv(netdev))->num_rx_queues) * \
(sizeof(struct ixgbe_stats) / sizeof(u64))) (sizeof(struct ixgbevf_stats) / sizeof(u64)))
#define IXGBEVF_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbevf_gstrings_stats) #define IXGBEVF_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbevf_gstrings_stats)
#define IXGBEVF_STATS_LEN (IXGBEVF_GLOBAL_STATS_LEN + IXGBEVF_QUEUE_STATS_LEN) #define IXGBEVF_STATS_LEN (IXGBEVF_GLOBAL_STATS_LEN + IXGBEVF_QUEUE_STATS_LEN)
...@@ -855,7 +855,8 @@ static int ixgbevf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, ...@@ -855,7 +855,8 @@ static int ixgbevf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) { if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) {
if (key) if (key)
memcpy(key, adapter->rss_key, sizeof(adapter->rss_key)); memcpy(key, adapter->rss_key,
ixgbevf_get_rxfh_key_size(netdev));
if (indir) { if (indir) {
int i; int i;
......
...@@ -319,7 +319,7 @@ struct ixgbevf_adapter { ...@@ -319,7 +319,7 @@ struct ixgbevf_adapter {
spinlock_t mbx_lock; spinlock_t mbx_lock;
unsigned long last_reset; unsigned long last_reset;
u32 rss_key[IXGBEVF_VFRSSRK_REGS]; u32 *rss_key;
u8 rss_indir_tbl[IXGBEVF_X550_VFRETA_SIZE]; u8 rss_indir_tbl[IXGBEVF_X550_VFRETA_SIZE];
}; };
......
...@@ -1660,6 +1660,28 @@ static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, ...@@ -1660,6 +1660,28 @@ static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter,
reg_idx); reg_idx);
} }
/**
* ixgbevf_init_rss_key - Initialize adapter RSS key
* @adapter: device handle
*
* Allocates and initializes the RSS key if it is not allocated.
**/
static inline int ixgbevf_init_rss_key(struct ixgbevf_adapter *adapter)
{
u32 *rss_key;
if (!adapter->rss_key) {
rss_key = kzalloc(IXGBEVF_RSS_HASH_KEY_SIZE, GFP_KERNEL);
if (unlikely(!rss_key))
return -ENOMEM;
netdev_rss_key_fill(rss_key, IXGBEVF_RSS_HASH_KEY_SIZE);
adapter->rss_key = rss_key;
}
return 0;
}
static void ixgbevf_setup_vfmrqc(struct ixgbevf_adapter *adapter) static void ixgbevf_setup_vfmrqc(struct ixgbevf_adapter *adapter)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
...@@ -1668,9 +1690,8 @@ static void ixgbevf_setup_vfmrqc(struct ixgbevf_adapter *adapter) ...@@ -1668,9 +1690,8 @@ static void ixgbevf_setup_vfmrqc(struct ixgbevf_adapter *adapter)
u8 i, j; u8 i, j;
/* Fill out hash function seeds */ /* Fill out hash function seeds */
netdev_rss_key_fill(adapter->rss_key, sizeof(adapter->rss_key));
for (i = 0; i < IXGBEVF_VFRSSRK_REGS; i++) for (i = 0; i < IXGBEVF_VFRSSRK_REGS; i++)
IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), adapter->rss_key[i]); IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), *(adapter->rss_key + i));
for (i = 0, j = 0; i < IXGBEVF_X550_VFRETA_SIZE; i++, j++) { for (i = 0, j = 0; i < IXGBEVF_X550_VFRETA_SIZE; i++, j++) {
if (j == rss_i) if (j == rss_i)
...@@ -2611,6 +2632,12 @@ static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter) ...@@ -2611,6 +2632,12 @@ static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
hw->mbx.ops.init_params(hw); hw->mbx.ops.init_params(hw);
if (hw->mac.type >= ixgbe_mac_X550_vf) {
err = ixgbevf_init_rss_key(adapter);
if (err)
goto out;
}
/* assume legacy case in which PF would only give VF 2 queues */ /* assume legacy case in which PF would only give VF 2 queues */
hw->mac.max_tx_queues = 2; hw->mac.max_tx_queues = 2;
hw->mac.max_rx_queues = 2; hw->mac.max_rx_queues = 2;
...@@ -4127,6 +4154,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -4127,6 +4154,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_sw_init: err_sw_init:
ixgbevf_reset_interrupt_capability(adapter); ixgbevf_reset_interrupt_capability(adapter);
iounmap(adapter->io_addr); iounmap(adapter->io_addr);
kfree(adapter->rss_key);
err_ioremap: err_ioremap:
disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state); disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state);
free_netdev(netdev); free_netdev(netdev);
...@@ -4173,6 +4201,7 @@ static void ixgbevf_remove(struct pci_dev *pdev) ...@@ -4173,6 +4201,7 @@ static void ixgbevf_remove(struct pci_dev *pdev)
hw_dbg(&adapter->hw, "Remove complete\n"); hw_dbg(&adapter->hw, "Remove complete\n");
kfree(adapter->rss_key);
disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state); disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state);
free_netdev(netdev); free_netdev(netdev);
......
...@@ -333,7 +333,7 @@ int ixgbevf_get_reta_locked(struct ixgbe_hw *hw, u32 *reta, int num_rx_queues) ...@@ -333,7 +333,7 @@ int ixgbevf_get_reta_locked(struct ixgbe_hw *hw, u32 *reta, int num_rx_queues)
switch (hw->api_version) { switch (hw->api_version) {
case ixgbe_mbox_api_13: case ixgbe_mbox_api_13:
case ixgbe_mbox_api_12: case ixgbe_mbox_api_12:
if (hw->mac.type >= ixgbe_mac_X550_vf) if (hw->mac.type < ixgbe_mac_X550_vf)
break; break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -399,7 +399,7 @@ int ixgbevf_get_rss_key_locked(struct ixgbe_hw *hw, u8 *rss_key) ...@@ -399,7 +399,7 @@ int ixgbevf_get_rss_key_locked(struct ixgbe_hw *hw, u8 *rss_key)
switch (hw->api_version) { switch (hw->api_version) {
case ixgbe_mbox_api_13: case ixgbe_mbox_api_13:
case ixgbe_mbox_api_12: case ixgbe_mbox_api_12:
if (hw->mac.type >= ixgbe_mac_X550_vf) if (hw->mac.type < ixgbe_mac_X550_vf)
break; break;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -419,7 +419,7 @@ int ixgbevf_get_rss_key_locked(struct ixgbe_hw *hw, u8 *rss_key) ...@@ -419,7 +419,7 @@ int ixgbevf_get_rss_key_locked(struct ixgbe_hw *hw, u8 *rss_key)
msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
/* If the operation has been refused by a PF return -EPERM */ /* If the operation has been refused by a PF return -EPERM */
if (msgbuf[0] == (IXGBE_VF_GET_RETA | IXGBE_VT_MSGTYPE_NACK)) if (msgbuf[0] == (IXGBE_VF_GET_RSS_KEY | IXGBE_VT_MSGTYPE_NACK))
return -EPERM; return -EPERM;
/* If we didn't get an ACK there must have been /* If we didn't get an ACK there must have been
......
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