sfc: Add support for Solarflare SFC9100 family

This adds support for the EF10 network controller architecture and the
SFC9100 family, starting with SFC9120 'Farmingdale', and bumps the
driver version to 4.0.

New features in the SFC9100 family include:

- Flexible allocation of internal resources to PCIe physical and virtual
  functions under firmware control
- RX event merging to reduce DMA writes at high packet rates
- Integrated RX timestamping
- PIO buffers for lower TX latency
- Firmware-driven data path that supports additional offload features
  and filter types
- Delivery of packets between functions and to multiple recipients,
  allowing firmware to implement a vswitch
- Multiple RX flow hash (RSS) contexts with their own hash keys and
  indirection tables
- 40G MAC (single port only)

...not all of which are enabled in this initial driver or the initial
firmware release.

Much of the new code is by Jon Cooper.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
This commit is contained in:
Ben Hutchings 2013-08-29 19:19:29 +01:00
parent 4c75b43a77
commit 8127d661e7
12 changed files with 3260 additions and 22 deletions

View File

@ -1,5 +1,5 @@
config SFC
tristate "Solarflare SFC4000/SFC9000-family support"
tristate "Solarflare SFC4000/SFC9000/SFC9100-family support"
depends on PCI
select MDIO
select CRC32
@ -8,12 +8,13 @@ config SFC
select PTP_1588_CLOCK
---help---
This driver supports 10-gigabit Ethernet cards based on
the Solarflare SFC4000 and SFC9000-family controllers.
the Solarflare SFC4000, SFC9000-family and SFC9100-family
controllers.
To compile this driver as a module, choose M here. The module
will be called sfc.
config SFC_MTD
bool "Solarflare SFC4000/SFC9000-family MTD support"
bool "Solarflare SFC4000/SFC9000/SFC9100-family MTD support"
depends on SFC && MTD && !(SFC=y && MTD=m)
default y
---help---
@ -21,7 +22,7 @@ config SFC_MTD
(e.g. /dev/mtd1). This is required to update the firmware or
the boot configuration under Linux.
config SFC_MCDI_MON
bool "Solarflare SFC9000-family hwmon support"
bool "Solarflare SFC9000/SFC9100-family hwmon support"
depends on SFC && HWMON && !(SFC=y && HWMON=m)
default y
---help---

View File

@ -1,5 +1,5 @@
sfc-y += efx.o nic.o farch.o falcon.o siena.o tx.o rx.o \
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \
rx.o selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
tenxpress.o txc43128_phy.o falcon_boards.o \
mcdi.o mcdi_port.o mcdi_mon.o ptp.o
sfc-$(CONFIG_SFC_MTD) += mtd.o

View File

@ -29,6 +29,10 @@
/* Lowest bit numbers and widths */
#define EFX_DUMMY_FIELD_LBN 0
#define EFX_DUMMY_FIELD_WIDTH 0
#define EFX_WORD_0_LBN 0
#define EFX_WORD_0_WIDTH 16
#define EFX_WORD_1_LBN 16
#define EFX_WORD_1_WIDTH 16
#define EFX_DWORD_0_LBN 0
#define EFX_DWORD_0_WIDTH 32
#define EFX_DWORD_1_LBN 32

File diff suppressed because it is too large Load Diff

View File

@ -2075,7 +2075,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
return 0;
}
static const struct net_device_ops efx_netdev_ops = {
static const struct net_device_ops efx_farch_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
.ndo_get_stats64 = efx_net_stats,
@ -2102,6 +2102,26 @@ static const struct net_device_ops efx_netdev_ops = {
#endif
};
static const struct net_device_ops efx_ef10_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
.ndo_get_stats64 = efx_net_stats,
.ndo_tx_timeout = efx_watchdog,
.ndo_start_xmit = efx_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = efx_ioctl,
.ndo_change_mtu = efx_change_mtu,
.ndo_set_mac_address = efx_set_mac_address,
.ndo_set_rx_mode = efx_set_rx_mode,
.ndo_set_features = efx_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
#endif
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = efx_filter_rfs,
#endif
};
static void efx_update_name(struct efx_nic *efx)
{
strcpy(efx->name, efx->net_dev->name);
@ -2114,7 +2134,8 @@ static int efx_netdev_event(struct notifier_block *this,
{
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
if (net_dev->netdev_ops == &efx_netdev_ops &&
if ((net_dev->netdev_ops == &efx_farch_netdev_ops ||
net_dev->netdev_ops == &efx_ef10_netdev_ops) &&
event == NETDEV_CHANGENAME)
efx_update_name(netdev_priv(net_dev));
@ -2141,7 +2162,12 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
net_dev->netdev_ops = &efx_netdev_ops;
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
net_dev->netdev_ops = &efx_ef10_netdev_ops;
net_dev->priv_flags |= IFF_UNICAST_FLT;
} else {
net_dev->netdev_ops = &efx_farch_netdev_ops;
}
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
@ -2463,6 +2489,8 @@ static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0813), /* SFL9021 */
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0903), /* SFC9120 PF */
.driver_data = (unsigned long) &efx_hunt_a0_nic_type},
{0} /* end of list */
};

View File

@ -77,6 +77,8 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
};
#define EFX_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(efx_sw_stat_desc)

View File

@ -852,6 +852,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
"MC Scheduler error address=0x%x\n", data);
break;
case MCDI_EVENT_CODE_REBOOT:
case MCDI_EVENT_CODE_MC_REBOOT:
netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
efx_mcdi_ev_death(efx, -EIO);
break;
@ -866,7 +867,19 @@ void efx_mcdi_process_event(struct efx_channel *channel,
case MCDI_EVENT_CODE_PTP_PPS:
efx_ptp_event(efx, event);
break;
case MCDI_EVENT_CODE_TX_FLUSH:
case MCDI_EVENT_CODE_RX_FLUSH:
/* Two flush events will be sent: one to the same event
* queue as completions, and one to event queue 0.
* In the latter case the {RX,TX}_FLUSH_TO_DRIVER
* flag will be set, and we should ignore the event
* because we want to wait for all completions.
*/
BUILD_BUG_ON(MCDI_EVENT_TX_FLUSH_TO_DRIVER_LBN !=
MCDI_EVENT_RX_FLUSH_TO_DRIVER_LBN);
if (!MCDI_EVENT_FIELD(*event, TX_FLUSH_TO_DRIVER))
efx_ef10_handle_drain_event(efx);
break;
case MCDI_EVENT_CODE_TX_ERR:
case MCDI_EVENT_CODE_RX_ERR:
netif_err(efx, hw, efx->net_dev,
@ -890,27 +903,55 @@ void efx_mcdi_process_event(struct efx_channel *channel,
void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_OUT_LEN);
MCDI_DECLARE_BUF(outbuf,
max(MC_CMD_GET_VERSION_OUT_LEN,
MC_CMD_GET_CAPABILITIES_OUT_LEN));
size_t outlength;
const __le16 *ver_words;
size_t offset;
int rc;
BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
outbuf, sizeof(outbuf), &outlength);
if (rc)
goto fail;
if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
rc = -EIO;
goto fail;
}
ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
snprintf(buf, len, "%u.%u.%u.%u",
le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
offset = snprintf(buf, len, "%u.%u.%u.%u",
le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
/* EF10 may have multiple datapath firmware variants within a
* single version. Report which variants are running.
*/
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
BUILD_BUG_ON(MC_CMD_GET_CAPABILITIES_IN_LEN != 0);
rc = efx_mcdi_rpc(efx, MC_CMD_GET_CAPABILITIES, NULL, 0,
outbuf, sizeof(outbuf), &outlength);
if (rc || outlength < MC_CMD_GET_CAPABILITIES_OUT_LEN)
offset += snprintf(
buf + offset, len - offset, " rx? tx?");
else
offset += snprintf(
buf + offset, len - offset, " rx%x tx%x",
MCDI_WORD(outbuf,
GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID),
MCDI_WORD(outbuf,
GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID));
/* It's theoretically possible for the string to exceed 31
* characters, though in practice the first three version
* components are short enough that this doesn't happen.
*/
if (WARN_ON(offset >= len))
buf[0] = 0;
}
return;
fail:
@ -1430,6 +1471,17 @@ fail:
return rc;
}
int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_WORKAROUND_IN_LEN);
BUILD_BUG_ON(MC_CMD_WORKAROUND_OUT_LEN != 0);
MCDI_SET_DWORD(inbuf, WORKAROUND_IN_TYPE, type);
MCDI_SET_DWORD(inbuf, WORKAROUND_IN_ENABLED, enabled);
return efx_mcdi_rpc(efx, MC_CMD_WORKAROUND, inbuf, sizeof(inbuf),
NULL, 0, NULL);
}
#ifdef CONFIG_SFC_MTD
#define EFX_MCDI_NVRAM_LEN_MAX 128

View File

@ -81,7 +81,7 @@ struct efx_mcdi_mon {
struct efx_mcdi_mtd_partition {
struct efx_mtd_partition common;
bool updating;
u8 nvram_type;
u16 nvram_type;
u16 fw_subtype;
};
@ -157,6 +157,9 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define _MCDI_DWORD(_buf, _field) \
((_buf) + (_MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, 4) >> 2))
#define MCDI_WORD(_buf, _field) \
((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \
le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))
#define MCDI_SET_DWORD(_buf, _field, _value) \
EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
#define MCDI_DWORD(_buf, _field) \
@ -293,6 +296,8 @@ extern int efx_mcdi_flush_rxqs(struct efx_nic *efx);
extern int efx_mcdi_port_probe(struct efx_nic *efx);
extern void efx_mcdi_port_remove(struct efx_nic *efx);
extern int efx_mcdi_port_reconfigure(struct efx_nic *efx);
extern int efx_mcdi_port_get_number(struct efx_nic *efx);
extern u32 efx_mcdi_phy_get_caps(struct efx_nic *efx);
extern void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
extern int efx_mcdi_set_mac(struct efx_nic *efx);
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
@ -301,6 +306,7 @@ extern void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
extern enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
extern int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
extern int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled);
#ifdef CONFIG_SFC_MCDI_MON
extern int efx_mcdi_mon_probe(struct efx_nic *efx);

View File

@ -830,6 +830,13 @@ static const struct efx_phy_operations efx_mcdi_phy_ops = {
.get_module_info = efx_mcdi_phy_get_module_info,
};
u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
{
struct efx_mcdi_phy_data *phy_data = efx->phy_data;
return phy_data->supported_cap;
}
static unsigned int efx_mcdi_event_link_speed[] = {
[MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
[MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
@ -1004,3 +1011,17 @@ void efx_mcdi_port_remove(struct efx_nic *efx)
efx->phy_op->remove(efx);
efx_nic_free_buffer(efx, &efx->stats_buffer);
}
/* Get physical port number (EF10 only; on Siena it is same as PF number) */
int efx_mcdi_port_get_number(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
int rc;
rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0,
outbuf, sizeof(outbuf), NULL);
if (rc)
return rc;
return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT);
}

View File

@ -39,7 +39,7 @@
*
**************************************************************************/
#define EFX_DRIVER_VERSION "3.2"
#define EFX_DRIVER_VERSION "4.0"
#ifdef DEBUG
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@ -389,6 +389,8 @@ enum efx_rx_alloc_method {
* @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
* @n_rx_nodesc_trunc: Number of RX packets truncated and then dropped due to
* lack of descriptors
* @n_rx_merge_events: Number of RX merged completion events
* @n_rx_merge_packets: Number of RX packets completed by merged events
* @rx_pkt_n_frags: Number of fragments in next packet to be delivered by
* __efx_rx_packet(), or zero if there is none
* @rx_pkt_index: Ring index of first buffer for next packet to be delivered
@ -425,6 +427,8 @@ struct efx_channel {
unsigned n_rx_overlength;
unsigned n_skbuff_leaks;
unsigned int n_rx_nodesc_trunc;
unsigned int n_rx_merge_events;
unsigned int n_rx_merge_packets;
unsigned int rx_pkt_n_frags;
unsigned int rx_pkt_index;

View File

@ -17,15 +17,12 @@
#include "efx.h"
#include "mcdi.h"
/*
* Falcon hardware control
*/
enum {
EFX_REV_FALCON_A0 = 0,
EFX_REV_FALCON_A1 = 1,
EFX_REV_FALCON_B0 = 2,
EFX_REV_SIENA_A0 = 3,
EFX_REV_HUNT_A0 = 4,
};
static inline int efx_nic_rev(struct efx_nic *efx)
@ -347,6 +344,78 @@ struct siena_nic_data {
u64 stats[SIENA_STAT_COUNT];
};
enum {
EF10_STAT_tx_bytes,
EF10_STAT_tx_packets,
EF10_STAT_tx_pause,
EF10_STAT_tx_control,
EF10_STAT_tx_unicast,
EF10_STAT_tx_multicast,
EF10_STAT_tx_broadcast,
EF10_STAT_tx_lt64,
EF10_STAT_tx_64,
EF10_STAT_tx_65_to_127,
EF10_STAT_tx_128_to_255,
EF10_STAT_tx_256_to_511,
EF10_STAT_tx_512_to_1023,
EF10_STAT_tx_1024_to_15xx,
EF10_STAT_tx_15xx_to_jumbo,
EF10_STAT_rx_bytes,
EF10_STAT_rx_bytes_minus_good_bytes,
EF10_STAT_rx_good_bytes,
EF10_STAT_rx_bad_bytes,
EF10_STAT_rx_packets,
EF10_STAT_rx_good,
EF10_STAT_rx_bad,
EF10_STAT_rx_pause,
EF10_STAT_rx_control,
EF10_STAT_rx_unicast,
EF10_STAT_rx_multicast,
EF10_STAT_rx_broadcast,
EF10_STAT_rx_lt64,
EF10_STAT_rx_64,
EF10_STAT_rx_65_to_127,
EF10_STAT_rx_128_to_255,
EF10_STAT_rx_256_to_511,
EF10_STAT_rx_512_to_1023,
EF10_STAT_rx_1024_to_15xx,
EF10_STAT_rx_15xx_to_jumbo,
EF10_STAT_rx_gtjumbo,
EF10_STAT_rx_bad_gtjumbo,
EF10_STAT_rx_overflow,
EF10_STAT_rx_align_error,
EF10_STAT_rx_length_error,
EF10_STAT_rx_nodesc_drops,
EF10_STAT_COUNT
};
/**
* struct efx_ef10_nic_data - EF10 architecture NIC state
* @mcdi_buf: DMA buffer for MCDI
* @warm_boot_count: Last seen MC warm boot count
* @vi_base: Absolute index of first VI in this function
* @n_allocated_vis: Number of VIs allocated to this function
* @must_realloc_vis: Flag: VIs have yet to be reallocated after MC reboot
* @must_restore_filters: Flag: filters have yet to be restored after MC reboot
* @rx_rss_context: Firmware handle for our RSS context
* @stats: Hardware statistics
* @workaround_35388: Flag: firmware supports workaround for bug 35388
* @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of
* %MC_CMD_GET_CAPABILITIES response)
*/
struct efx_ef10_nic_data {
struct efx_buffer mcdi_buf;
u16 warm_boot_count;
unsigned int vi_base;
unsigned int n_allocated_vis;
bool must_realloc_vis;
bool must_restore_filters;
u32 rx_rss_context;
u64 stats[EF10_STAT_COUNT];
bool workaround_35388;
u32 datapath_caps;
};
/*
* On the SFC9000 family each port is associated with 1 PCI physical
* function (PF) handled by sfc and a configurable number of virtual
@ -448,6 +517,7 @@ extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type;
extern const struct efx_nic_type siena_a0_nic_type;
extern const struct efx_nic_type efx_hunt_a0_nic_type;
/**************************************************************************
*
@ -627,6 +697,7 @@ extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
extern void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
extern void efx_farch_init_common(struct efx_nic *efx);
extern void efx_ef10_handle_drain_event(struct efx_nic *efx);
static inline void efx_nic_push_rx_indir_table(struct efx_nic *efx)
{
efx->type->rx_push_indir_table(efx);

View File

@ -44,4 +44,10 @@
/* Leak overlength packets rather than free */
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
/* Lockup when writing event block registers at gen2/gen3 */
#define EFX_EF10_WORKAROUND_35388(efx) \
(((struct efx_ef10_nic_data *)efx->nic_data)->workaround_35388)
#define EFX_WORKAROUND_35388(efx) \
(efx_nic_rev(efx) == EFX_REV_HUNT_A0 && EFX_EF10_WORKAROUND_35388(efx))
#endif /* EFX_WORKAROUNDS_H */