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:
parent
4c75b43a77
commit
8127d661e7
@ -1,5 +1,5 @@
|
|||||||
config SFC
|
config SFC
|
||||||
tristate "Solarflare SFC4000/SFC9000-family support"
|
tristate "Solarflare SFC4000/SFC9000/SFC9100-family support"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
select MDIO
|
select MDIO
|
||||||
select CRC32
|
select CRC32
|
||||||
@ -8,12 +8,13 @@ config SFC
|
|||||||
select PTP_1588_CLOCK
|
select PTP_1588_CLOCK
|
||||||
---help---
|
---help---
|
||||||
This driver supports 10-gigabit Ethernet cards based on
|
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
|
To compile this driver as a module, choose M here. The module
|
||||||
will be called sfc.
|
will be called sfc.
|
||||||
config SFC_MTD
|
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)
|
depends on SFC && MTD && !(SFC=y && MTD=m)
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
@ -21,7 +22,7 @@ config SFC_MTD
|
|||||||
(e.g. /dev/mtd1). This is required to update the firmware or
|
(e.g. /dev/mtd1). This is required to update the firmware or
|
||||||
the boot configuration under Linux.
|
the boot configuration under Linux.
|
||||||
config SFC_MCDI_MON
|
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)
|
depends on SFC && HWMON && !(SFC=y && HWMON=m)
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
sfc-y += efx.o nic.o farch.o falcon.o siena.o tx.o rx.o \
|
sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \
|
||||||
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
|
rx.o selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
|
||||||
tenxpress.o txc43128_phy.o falcon_boards.o \
|
tenxpress.o txc43128_phy.o falcon_boards.o \
|
||||||
mcdi.o mcdi_port.o mcdi_mon.o ptp.o
|
mcdi.o mcdi_port.o mcdi_mon.o ptp.o
|
||||||
sfc-$(CONFIG_SFC_MTD) += mtd.o
|
sfc-$(CONFIG_SFC_MTD) += mtd.o
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
/* Lowest bit numbers and widths */
|
/* Lowest bit numbers and widths */
|
||||||
#define EFX_DUMMY_FIELD_LBN 0
|
#define EFX_DUMMY_FIELD_LBN 0
|
||||||
#define EFX_DUMMY_FIELD_WIDTH 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_LBN 0
|
||||||
#define EFX_DWORD_0_WIDTH 32
|
#define EFX_DWORD_0_WIDTH 32
|
||||||
#define EFX_DWORD_1_LBN 32
|
#define EFX_DWORD_1_LBN 32
|
||||||
|
3043
drivers/net/ethernet/sfc/ef10.c
Normal file
3043
drivers/net/ethernet/sfc/ef10.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -2075,7 +2075,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
|
|||||||
return 0;
|
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_open = efx_net_open,
|
||||||
.ndo_stop = efx_net_stop,
|
.ndo_stop = efx_net_stop,
|
||||||
.ndo_get_stats64 = efx_net_stats,
|
.ndo_get_stats64 = efx_net_stats,
|
||||||
@ -2102,6 +2102,26 @@ static const struct net_device_ops efx_netdev_ops = {
|
|||||||
#endif
|
#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)
|
static void efx_update_name(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
strcpy(efx->name, efx->net_dev->name);
|
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);
|
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)
|
event == NETDEV_CHANGENAME)
|
||||||
efx_update_name(netdev_priv(net_dev));
|
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->watchdog_timeo = 5 * HZ;
|
||||||
net_dev->irq = efx->pci_dev->irq;
|
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);
|
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
|
||||||
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
|
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},
|
.driver_data = (unsigned long) &siena_a0_nic_type},
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0813), /* SFL9021 */
|
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0813), /* SFL9021 */
|
||||||
.driver_data = (unsigned long) &siena_a0_nic_type},
|
.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 */
|
{0} /* end of list */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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_mcast_mismatch),
|
||||||
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
|
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
|
||||||
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_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)
|
#define EFX_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(efx_sw_stat_desc)
|
||||||
|
@ -852,6 +852,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
|
|||||||
"MC Scheduler error address=0x%x\n", data);
|
"MC Scheduler error address=0x%x\n", data);
|
||||||
break;
|
break;
|
||||||
case MCDI_EVENT_CODE_REBOOT:
|
case MCDI_EVENT_CODE_REBOOT:
|
||||||
|
case MCDI_EVENT_CODE_MC_REBOOT:
|
||||||
netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
|
netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
|
||||||
efx_mcdi_ev_death(efx, -EIO);
|
efx_mcdi_ev_death(efx, -EIO);
|
||||||
break;
|
break;
|
||||||
@ -866,7 +867,19 @@ void efx_mcdi_process_event(struct efx_channel *channel,
|
|||||||
case MCDI_EVENT_CODE_PTP_PPS:
|
case MCDI_EVENT_CODE_PTP_PPS:
|
||||||
efx_ptp_event(efx, event);
|
efx_ptp_event(efx, event);
|
||||||
break;
|
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_TX_ERR:
|
||||||
case MCDI_EVENT_CODE_RX_ERR:
|
case MCDI_EVENT_CODE_RX_ERR:
|
||||||
netif_err(efx, hw, efx->net_dev,
|
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)
|
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;
|
size_t outlength;
|
||||||
const __le16 *ver_words;
|
const __le16 *ver_words;
|
||||||
|
size_t offset;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
|
BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
|
||||||
|
|
||||||
rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
|
rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
|
||||||
outbuf, sizeof(outbuf), &outlength);
|
outbuf, sizeof(outbuf), &outlength);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
|
if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
|
ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
|
||||||
snprintf(buf, len, "%u.%u.%u.%u",
|
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[0]), le16_to_cpu(ver_words[1]),
|
||||||
le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
|
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;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -1430,6 +1471,17 @@ fail:
|
|||||||
return rc;
|
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
|
#ifdef CONFIG_SFC_MTD
|
||||||
|
|
||||||
#define EFX_MCDI_NVRAM_LEN_MAX 128
|
#define EFX_MCDI_NVRAM_LEN_MAX 128
|
||||||
|
@ -81,7 +81,7 @@ struct efx_mcdi_mon {
|
|||||||
struct efx_mcdi_mtd_partition {
|
struct efx_mcdi_mtd_partition {
|
||||||
struct efx_mtd_partition common;
|
struct efx_mtd_partition common;
|
||||||
bool updating;
|
bool updating;
|
||||||
u8 nvram_type;
|
u16 nvram_type;
|
||||||
u16 fw_subtype;
|
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) \
|
#define _MCDI_DWORD(_buf, _field) \
|
||||||
((_buf) + (_MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, 4) >> 2))
|
((_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) \
|
#define MCDI_SET_DWORD(_buf, _field, _value) \
|
||||||
EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
|
EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
|
||||||
#define MCDI_DWORD(_buf, _field) \
|
#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 int efx_mcdi_port_probe(struct efx_nic *efx);
|
||||||
extern void efx_mcdi_port_remove(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_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 void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
|
||||||
extern int efx_mcdi_set_mac(struct efx_nic *efx);
|
extern int efx_mcdi_set_mac(struct efx_nic *efx);
|
||||||
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
|
#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 bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
|
||||||
extern enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
|
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_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
|
#ifdef CONFIG_SFC_MCDI_MON
|
||||||
extern int efx_mcdi_mon_probe(struct efx_nic *efx);
|
extern int efx_mcdi_mon_probe(struct efx_nic *efx);
|
||||||
|
@ -830,6 +830,13 @@ static const struct efx_phy_operations efx_mcdi_phy_ops = {
|
|||||||
.get_module_info = efx_mcdi_phy_get_module_info,
|
.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[] = {
|
static unsigned int efx_mcdi_event_link_speed[] = {
|
||||||
[MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
|
[MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
|
||||||
[MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
|
[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->phy_op->remove(efx);
|
||||||
efx_nic_free_buffer(efx, &efx->stats_buffer);
|
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);
|
||||||
|
}
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define EFX_DRIVER_VERSION "3.2"
|
#define EFX_DRIVER_VERSION "4.0"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
|
#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_skbuff_leaks: Count of skbuffs leaked due to RX overrun
|
||||||
* @n_rx_nodesc_trunc: Number of RX packets truncated and then dropped due to
|
* @n_rx_nodesc_trunc: Number of RX packets truncated and then dropped due to
|
||||||
* lack of descriptors
|
* 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
|
* @rx_pkt_n_frags: Number of fragments in next packet to be delivered by
|
||||||
* __efx_rx_packet(), or zero if there is none
|
* __efx_rx_packet(), or zero if there is none
|
||||||
* @rx_pkt_index: Ring index of first buffer for next packet to be delivered
|
* @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_rx_overlength;
|
||||||
unsigned n_skbuff_leaks;
|
unsigned n_skbuff_leaks;
|
||||||
unsigned int n_rx_nodesc_trunc;
|
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_n_frags;
|
||||||
unsigned int rx_pkt_index;
|
unsigned int rx_pkt_index;
|
||||||
|
@ -17,15 +17,12 @@
|
|||||||
#include "efx.h"
|
#include "efx.h"
|
||||||
#include "mcdi.h"
|
#include "mcdi.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Falcon hardware control
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
EFX_REV_FALCON_A0 = 0,
|
EFX_REV_FALCON_A0 = 0,
|
||||||
EFX_REV_FALCON_A1 = 1,
|
EFX_REV_FALCON_A1 = 1,
|
||||||
EFX_REV_FALCON_B0 = 2,
|
EFX_REV_FALCON_B0 = 2,
|
||||||
EFX_REV_SIENA_A0 = 3,
|
EFX_REV_SIENA_A0 = 3,
|
||||||
|
EFX_REV_HUNT_A0 = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int efx_nic_rev(struct efx_nic *efx)
|
static inline int efx_nic_rev(struct efx_nic *efx)
|
||||||
@ -347,6 +344,78 @@ struct siena_nic_data {
|
|||||||
u64 stats[SIENA_STAT_COUNT];
|
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
|
* On the SFC9000 family each port is associated with 1 PCI physical
|
||||||
* function (PF) handled by sfc and a configurable number of virtual
|
* 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_a1_nic_type;
|
||||||
extern const struct efx_nic_type falcon_b0_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 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 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_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
|
||||||
extern void efx_farch_init_common(struct efx_nic *efx);
|
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)
|
static inline void efx_nic_push_rx_indir_table(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
efx->type->rx_push_indir_table(efx);
|
efx->type->rx_push_indir_table(efx);
|
||||||
|
@ -44,4 +44,10 @@
|
|||||||
/* Leak overlength packets rather than free */
|
/* Leak overlength packets rather than free */
|
||||||
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
|
#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 */
|
#endif /* EFX_WORKAROUNDS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user