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

Merge branch 'sfc-driver-for-EF100-family-NICs-part-2'

Edward Cree says:

====================
sfc: driver for EF100 family NICs, part 2

This series implements the data path and various other functionality
 for Xilinx/Solarflare EF100 NICs.

Changed from v2:
 * Improved error handling of design params (patch #3)
 * Removed 'inline' from .c file in patch #4
 * Don't report common stats to ethtool -S (patch #8)

Changed from v1:
 * Fixed build errors on CONFIG_RFS_ACCEL=n (patch #5) and 32-bit
   (patch #8)
 * Dropped patch #10 (ethtool ops) as it's buggy and will need a
   bigger rework to fix.
====================
Acked-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 215602a8 d61592a1
...@@ -527,6 +527,8 @@ static int ef100_pci_probe(struct pci_dev *pci_dev, ...@@ -527,6 +527,8 @@ static int ef100_pci_probe(struct pci_dev *pci_dev,
static const struct pci_device_id ef100_pci_table[] = { static const struct pci_device_id ef100_pci_table[] = {
{PCI_DEVICE(PCI_VENDOR_ID_XILINX, 0x0100), /* Riverhead PF */ {PCI_DEVICE(PCI_VENDOR_ID_XILINX, 0x0100), /* Riverhead PF */
.driver_data = (unsigned long) &ef100_pf_nic_type }, .driver_data = (unsigned long) &ef100_pf_nic_type },
{PCI_DEVICE(PCI_VENDOR_ID_XILINX, 0x1100), /* Riverhead VF */
.driver_data = (unsigned long) &ef100_vf_nic_type },
{0} /* end of list */ {0} /* end of list */
}; };
......
...@@ -86,9 +86,11 @@ static int ef100_net_stop(struct net_device *net_dev) ...@@ -86,9 +86,11 @@ static int ef100_net_stop(struct net_device *net_dev)
netif_stop_queue(net_dev); netif_stop_queue(net_dev);
efx_stop_all(efx); efx_stop_all(efx);
efx_mcdi_mac_fini_stats(efx);
efx_disable_interrupts(efx); efx_disable_interrupts(efx);
efx_clear_interrupt_affinity(efx); efx_clear_interrupt_affinity(efx);
efx_nic_fini_interrupt(efx); efx_nic_fini_interrupt(efx);
efx_remove_filters(efx);
efx_fini_napi(efx); efx_fini_napi(efx);
efx_remove_channels(efx); efx_remove_channels(efx);
efx_mcdi_free_vis(efx); efx_mcdi_free_vis(efx);
...@@ -138,6 +140,10 @@ static int ef100_net_open(struct net_device *net_dev) ...@@ -138,6 +140,10 @@ static int ef100_net_open(struct net_device *net_dev)
efx_init_napi(efx); efx_init_napi(efx);
rc = efx_probe_filters(efx);
if (rc)
goto fail;
rc = efx_nic_init_interrupt(efx); rc = efx_nic_init_interrupt(efx);
if (rc) if (rc)
goto fail; goto fail;
...@@ -152,6 +158,10 @@ static int ef100_net_open(struct net_device *net_dev) ...@@ -152,6 +158,10 @@ static int ef100_net_open(struct net_device *net_dev)
*/ */
(void) efx_mcdi_poll_reboot(efx); (void) efx_mcdi_poll_reboot(efx);
rc = efx_mcdi_mac_init_stats(efx);
if (rc)
goto fail;
efx_start_all(efx); efx_start_all(efx);
/* Link state detection is normally event-driven; we have /* Link state detection is normally event-driven; we have
...@@ -207,8 +217,14 @@ static const struct net_device_ops ef100_netdev_ops = { ...@@ -207,8 +217,14 @@ static const struct net_device_ops ef100_netdev_ops = {
.ndo_open = ef100_net_open, .ndo_open = ef100_net_open,
.ndo_stop = ef100_net_stop, .ndo_stop = ef100_net_stop,
.ndo_start_xmit = ef100_hard_start_xmit, .ndo_start_xmit = ef100_hard_start_xmit,
.ndo_get_stats64 = efx_net_stats,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = efx_set_rx_mode, /* Lookout */
.ndo_get_phys_port_id = efx_get_phys_port_id, .ndo_get_phys_port_id = efx_get_phys_port_id,
.ndo_get_phys_port_name = efx_get_phys_port_name, .ndo_get_phys_port_name = efx_get_phys_port_name,
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = efx_filter_rfs,
#endif
}; };
/* Netdev registration /* Netdev registration
......
This diff is collapsed.
...@@ -13,19 +13,67 @@ ...@@ -13,19 +13,67 @@
#include "nic_common.h" #include "nic_common.h"
extern const struct efx_nic_type ef100_pf_nic_type; extern const struct efx_nic_type ef100_pf_nic_type;
extern const struct efx_nic_type ef100_vf_nic_type;
int ef100_probe_pf(struct efx_nic *efx); int ef100_probe_pf(struct efx_nic *efx);
int ef100_probe_vf(struct efx_nic *efx);
void ef100_remove(struct efx_nic *efx); void ef100_remove(struct efx_nic *efx);
enum {
EF100_STAT_port_tx_bytes = GENERIC_STAT_COUNT,
EF100_STAT_port_tx_packets,
EF100_STAT_port_tx_pause,
EF100_STAT_port_tx_unicast,
EF100_STAT_port_tx_multicast,
EF100_STAT_port_tx_broadcast,
EF100_STAT_port_tx_lt64,
EF100_STAT_port_tx_64,
EF100_STAT_port_tx_65_to_127,
EF100_STAT_port_tx_128_to_255,
EF100_STAT_port_tx_256_to_511,
EF100_STAT_port_tx_512_to_1023,
EF100_STAT_port_tx_1024_to_15xx,
EF100_STAT_port_tx_15xx_to_jumbo,
EF100_STAT_port_rx_bytes,
EF100_STAT_port_rx_packets,
EF100_STAT_port_rx_good,
EF100_STAT_port_rx_bad,
EF100_STAT_port_rx_pause,
EF100_STAT_port_rx_unicast,
EF100_STAT_port_rx_multicast,
EF100_STAT_port_rx_broadcast,
EF100_STAT_port_rx_lt64,
EF100_STAT_port_rx_64,
EF100_STAT_port_rx_65_to_127,
EF100_STAT_port_rx_128_to_255,
EF100_STAT_port_rx_256_to_511,
EF100_STAT_port_rx_512_to_1023,
EF100_STAT_port_rx_1024_to_15xx,
EF100_STAT_port_rx_15xx_to_jumbo,
EF100_STAT_port_rx_gtjumbo,
EF100_STAT_port_rx_bad_gtjumbo,
EF100_STAT_port_rx_align_error,
EF100_STAT_port_rx_length_error,
EF100_STAT_port_rx_overflow,
EF100_STAT_port_rx_nodesc_drops,
EF100_STAT_COUNT
};
struct ef100_nic_data { struct ef100_nic_data {
struct efx_nic *efx; struct efx_nic *efx;
struct efx_buffer mcdi_buf; struct efx_buffer mcdi_buf;
u32 datapath_caps; u32 datapath_caps;
u32 datapath_caps2; u32 datapath_caps2;
u32 datapath_caps3; u32 datapath_caps3;
unsigned int pf_index;
u16 warm_boot_count; u16 warm_boot_count;
u8 port_id[ETH_ALEN]; u8 port_id[ETH_ALEN];
DECLARE_BITMAP(evq_phases, EFX_MAX_CHANNELS); DECLARE_BITMAP(evq_phases, EFX_MAX_CHANNELS);
u64 stats[EF100_STAT_COUNT];
u16 tso_max_hdr_len;
u16 tso_max_payload_num_segs;
u16 tso_max_frames;
unsigned int tso_max_payload_len;
}; };
#define efx_ef100_has_cap(caps, flag) \ #define efx_ef100_has_cap(caps, flag) \
......
...@@ -12,20 +12,156 @@ ...@@ -12,20 +12,156 @@
#include "ef100_rx.h" #include "ef100_rx.h"
#include "rx_common.h" #include "rx_common.h"
#include "efx.h" #include "efx.h"
#include "nic_common.h"
#include "mcdi_functions.h"
#include "ef100_regs.h"
#include "ef100_nic.h"
#include "io.h"
/* RX stubs */ /* Get the value of a field in the RX prefix */
#define PREFIX_OFFSET_W(_f) (ESF_GZ_RX_PREFIX_ ## _f ## _LBN / 32)
#define PREFIX_OFFSET_B(_f) (ESF_GZ_RX_PREFIX_ ## _f ## _LBN % 32)
#define PREFIX_WIDTH_MASK(_f) ((1UL << ESF_GZ_RX_PREFIX_ ## _f ## _WIDTH) - 1)
#define PREFIX_WORD(_p, _f) le32_to_cpu((__force __le32)(_p)[PREFIX_OFFSET_W(_f)])
#define PREFIX_FIELD(_p, _f) ((PREFIX_WORD(_p, _f) >> PREFIX_OFFSET_B(_f)) & \
PREFIX_WIDTH_MASK(_f))
void ef100_rx_write(struct efx_rx_queue *rx_queue) #define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_LBN \
(ESF_GZ_RX_PREFIX_CLASS_LBN + ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_LBN)
#define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_WIDTH \
ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_WIDTH
static bool check_fcs(struct efx_channel *channel, u32 *prefix)
{ {
u16 rxclass;
u8 l2status;
rxclass = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, CLASS));
l2status = PREFIX_FIELD(&rxclass, HCLASS_L2_STATUS);
if (likely(l2status == ESE_GZ_RH_HCLASS_L2_STATUS_OK))
/* Everything is ok */
return 0;
if (l2status == ESE_GZ_RH_HCLASS_L2_STATUS_FCS_ERR)
channel->n_rx_eth_crc_err++;
return 1;
} }
void __ef100_rx_packet(struct efx_channel *channel) void __ef100_rx_packet(struct efx_channel *channel)
{ {
/* Stub. No RX path yet. Discard the buffer. */ struct efx_rx_buffer *rx_buf = efx_rx_buffer(&channel->rx_queue, channel->rx_pkt_index);
struct efx_rx_buffer *rx_buf = efx_rx_buffer(&channel->rx_queue, struct efx_nic *efx = channel->efx;
channel->rx_pkt_index); u8 *eh = efx_rx_buf_va(rx_buf);
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); __wsum csum = 0;
u32 *prefix;
prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN);
if (check_fcs(channel, prefix) &&
unlikely(!(efx->net_dev->features & NETIF_F_RXALL)))
goto out;
rx_buf->len = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, LENGTH));
if (rx_buf->len <= sizeof(struct ethhdr)) {
if (net_ratelimit())
netif_err(channel->efx, rx_err, channel->efx->net_dev,
"RX packet too small (%d)\n", rx_buf->len);
++channel->n_rx_frm_trunc;
goto out;
}
if (likely(efx->net_dev->features & NETIF_F_RXCSUM)) {
if (PREFIX_FIELD(prefix, NT_OR_INNER_L3_CLASS) == 1) {
++channel->n_rx_ip_hdr_chksum_err;
} else {
u16 sum = be16_to_cpu((__force __be16)PREFIX_FIELD(prefix, CSUM_FRAME));
efx_free_rx_buffers(rx_queue, rx_buf, 1); csum = (__force __wsum) sum;
}
}
if (channel->type->receive_skb) {
struct efx_rx_queue *rx_queue =
efx_channel_get_rx_queue(channel);
/* no support for special channels yet, so just discard */
WARN_ON_ONCE(1);
efx_free_rx_buffers(rx_queue, rx_buf, 1);
goto out;
}
efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh, csum);
out:
channel->rx_pkt_n_frags = 0; channel->rx_pkt_n_frags = 0;
} }
static void ef100_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index)
{
struct efx_rx_buffer *rx_buf = efx_rx_buffer(rx_queue, index);
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_nic *efx = rx_queue->efx;
++rx_queue->rx_packets;
netif_vdbg(efx, rx_status, efx->net_dev,
"RX queue %d received id %x\n",
efx_rx_queue_index(rx_queue), index);
efx_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);
prefetch(efx_rx_buf_va(rx_buf));
rx_buf->page_offset += efx->rx_prefix_size;
efx_recycle_rx_pages(channel, rx_buf, 1);
efx_rx_flush_packet(channel);
channel->rx_pkt_n_frags = 1;
channel->rx_pkt_index = index;
}
void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event)
{
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
unsigned int n_packets =
EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_RXPKTS_NUM_PKT);
int i;
WARN_ON_ONCE(!n_packets);
if (n_packets > 1)
++channel->n_rx_merge_events;
channel->irq_mod_score += 2 * n_packets;
for (i = 0; i < n_packets; ++i) {
ef100_rx_packet(rx_queue,
rx_queue->removed_count & rx_queue->ptr_mask);
++rx_queue->removed_count;
}
}
void ef100_rx_write(struct efx_rx_queue *rx_queue)
{
struct efx_rx_buffer *rx_buf;
unsigned int idx;
efx_qword_t *rxd;
efx_dword_t rxdb;
while (rx_queue->notified_count != rx_queue->added_count) {
idx = rx_queue->notified_count & rx_queue->ptr_mask;
rx_buf = efx_rx_buffer(rx_queue, idx);
rxd = efx_rx_desc(rx_queue, idx);
EFX_POPULATE_QWORD_1(*rxd, ESF_GZ_RX_BUF_ADDR, rx_buf->dma_addr);
++rx_queue->notified_count;
}
wmb();
EFX_POPULATE_DWORD_1(rxdb, ERF_GZ_RX_RING_PIDX,
rx_queue->added_count & rx_queue->ptr_mask);
efx_writed_page(rx_queue->efx, &rxdb,
ER_GZ_RX_RING_DOORBELL, efx_rx_queue_index(rx_queue));
}
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "net_driver.h" #include "net_driver.h"
void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event);
void ef100_rx_write(struct efx_rx_queue *rx_queue); void ef100_rx_write(struct efx_rx_queue *rx_queue);
void __ef100_rx_packet(struct efx_channel *channel); void __ef100_rx_packet(struct efx_channel *channel);
......
This diff is collapsed.
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
int ef100_tx_probe(struct efx_tx_queue *tx_queue); int ef100_tx_probe(struct efx_tx_queue *tx_queue);
void ef100_tx_init(struct efx_tx_queue *tx_queue); void ef100_tx_init(struct efx_tx_queue *tx_queue);
void ef100_tx_write(struct efx_tx_queue *tx_queue); void ef100_tx_write(struct efx_tx_queue *tx_queue);
void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue);
unsigned int ef100_tx_max_skb_descs(struct efx_nic *efx);
void ef100_ev_tx(struct efx_channel *channel, const efx_qword_t *p_event);
netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); netdev_tx_t ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
#endif #endif
...@@ -173,6 +173,7 @@ struct efx_tx_buffer { ...@@ -173,6 +173,7 @@ struct efx_tx_buffer {
#define EFX_TX_BUF_MAP_SINGLE 8 /* buffer was mapped with dma_map_single() */ #define EFX_TX_BUF_MAP_SINGLE 8 /* buffer was mapped with dma_map_single() */
#define EFX_TX_BUF_OPTION 0x10 /* empty buffer for option descriptor */ #define EFX_TX_BUF_OPTION 0x10 /* empty buffer for option descriptor */
#define EFX_TX_BUF_XDP 0x20 /* buffer was sent with XDP */ #define EFX_TX_BUF_XDP 0x20 /* buffer was sent with XDP */
#define EFX_TX_BUF_TSO_V3 0x40 /* empty buffer for a TSO_V3 descriptor */
/** /**
* struct efx_tx_queue - An Efx TX queue * struct efx_tx_queue - An Efx TX queue
...@@ -245,6 +246,7 @@ struct efx_tx_buffer { ...@@ -245,6 +246,7 @@ struct efx_tx_buffer {
* @pio_packets: Number of times the TX PIO feature has been used * @pio_packets: Number of times the TX PIO feature has been used
* @xmit_more_available: Are any packets waiting to be pushed to the NIC * @xmit_more_available: Are any packets waiting to be pushed to the NIC
* @cb_packets: Number of times the TX copybreak feature has been used * @cb_packets: Number of times the TX copybreak feature has been used
* @notify_count: Count of notified descriptors to the NIC
* @empty_read_count: If the completion path has seen the queue as empty * @empty_read_count: If the completion path has seen the queue as empty
* and the transmission path has not yet checked this, the value of * and the transmission path has not yet checked this, the value of
* @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0. * @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
...@@ -292,6 +294,7 @@ struct efx_tx_queue { ...@@ -292,6 +294,7 @@ struct efx_tx_queue {
unsigned int pio_packets; unsigned int pio_packets;
bool xmit_more_available; bool xmit_more_available;
unsigned int cb_packets; unsigned int cb_packets;
unsigned int notify_count;
/* Statistics to supplement MAC stats */ /* Statistics to supplement MAC stats */
unsigned long tx_packets; unsigned long tx_packets;
...@@ -1669,6 +1672,24 @@ static inline void efx_xmit_hwtstamp_pending(struct sk_buff *skb) ...@@ -1669,6 +1672,24 @@ static inline void efx_xmit_hwtstamp_pending(struct sk_buff *skb)
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
} }
/* Get the max fill level of the TX queues on this channel */
static inline unsigned int
efx_channel_tx_fill_level(struct efx_channel *channel)
{
struct efx_tx_queue *tx_queue;
unsigned int fill_level = 0;
/* This function is currently only used by EF100, which maybe
* could do something simpler and just compute the fill level
* of the single TXQ that's really in use.
*/
efx_for_each_channel_tx_queue(tx_queue, channel)
fill_level = max(fill_level,
tx_queue->insert_count - tx_queue->read_count);
return fill_level;
}
/* Get all supported features. /* Get all supported features.
* If a feature is not fixed, it is present in hw_features. * If a feature is not fixed, it is present in hw_features.
* If a feature is fixed, it does not present in hw_features, but * If a feature is fixed, it does not present in hw_features, but
......
...@@ -71,6 +71,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue) ...@@ -71,6 +71,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
"initialising TX queue %d\n", tx_queue->queue); "initialising TX queue %d\n", tx_queue->queue);
tx_queue->insert_count = 0; tx_queue->insert_count = 0;
tx_queue->notify_count = 0;
tx_queue->write_count = 0; tx_queue->write_count = 0;
tx_queue->packet_write_count = 0; tx_queue->packet_write_count = 0;
tx_queue->old_write_count = 0; tx_queue->old_write_count = 0;
......
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