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

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next

Ben Hutchings says:

====================
Miscellaneous changes for 3.14:

1. Add more information to some WARN messages.
2. Refactor pushing of RSS configuration, from Andrew Rybchenko.
3. Refactor handling of automatic (device address list) vs manual (RX
NFC) MAC filters.
4. Implement clearing of manual RX filters on EF10 when ntuple offload
is disabled.
5. Remove definitions that are unused since the RX buffer allocation
changes, from Andrew Rybchenko.
6. Improve naming of some statistics, from Shradha Shah.
7. Add statistics for PTP support code.
8. Fix insertion of RX drop filters on EF10.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f66fd2dd a0bc3487
This diff is collapsed.
......@@ -2151,7 +2151,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
/* If disabling RX n-tuple filtering, clear existing filters */
if (net_dev->features & ~data & NETIF_F_NTUPLE)
efx_filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
return efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL);
return 0;
}
......
......@@ -134,17 +134,6 @@ efx_filter_get_filter_safe(struct efx_nic *efx,
return efx->type->filter_get_safe(efx, priority, filter_id, spec);
}
/**
* efx_farch_filter_clear_rx - remove RX filters by priority
* @efx: NIC from which to remove the filters
* @priority: Maximum priority to remove
*/
static inline void efx_filter_clear_rx(struct efx_nic *efx,
enum efx_filter_priority priority)
{
return efx->type->filter_clear_rx(efx, priority);
}
static inline u32 efx_filter_count_rx_used(struct efx_nic *efx,
enum efx_filter_priority priority)
{
......
......@@ -359,7 +359,8 @@ static int efx_ethtool_get_sset_count(struct net_device *net_dev,
switch (string_set) {
case ETH_SS_STATS:
return efx->type->describe_stats(efx, NULL) +
EFX_ETHTOOL_SW_STAT_COUNT;
EFX_ETHTOOL_SW_STAT_COUNT +
efx_ptp_describe_stats(efx, NULL);
case ETH_SS_TEST:
return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
default:
......@@ -380,6 +381,8 @@ static void efx_ethtool_get_strings(struct net_device *net_dev,
for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++)
strlcpy(strings + i * ETH_GSTRING_LEN,
efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
efx_ptp_describe_stats(efx, strings);
break;
case ETH_SS_TEST:
efx_ethtool_fill_self_tests(efx, NULL, strings, NULL);
......@@ -429,8 +432,11 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
break;
}
}
data += EFX_ETHTOOL_SW_STAT_COUNT;
spin_unlock_bh(&efx->stats_lock);
efx_ptp_update_stats(efx, data);
}
static void efx_ethtool_self_test(struct net_device *net_dev,
......@@ -1034,7 +1040,7 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
memcpy(efx->rx_indir_table, indir, sizeof(efx->rx_indir_table));
efx_nic_push_rx_indir_table(efx);
efx->type->rx_push_rss_config(efx);
return 0;
}
......
......@@ -467,6 +467,24 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
efx_schedule_channel_irq(efx_get_channel(efx, 1));
return IRQ_HANDLED;
}
/**************************************************************************
*
* RSS
*
**************************************************************************
*/
static void falcon_b0_rx_push_rss_config(struct efx_nic *efx)
{
efx_oword_t temp;
/* Set hash key for IPv4 */
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
efx_farch_rx_push_indir_table(efx);
}
/**************************************************************************
*
* EEPROM/flash
......@@ -2484,9 +2502,7 @@ static int falcon_init_nic(struct efx_nic *efx)
falcon_init_rx_cfg(efx);
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
/* Set hash key for IPv4 */
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
falcon_b0_rx_push_rss_config(efx);
/* Set destination of both TX and RX Flush events */
EFX_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0);
......@@ -2703,7 +2719,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.tx_init = efx_farch_tx_init,
.tx_remove = efx_farch_tx_remove,
.tx_write = efx_farch_tx_write,
.rx_push_indir_table = efx_farch_rx_push_indir_table,
.rx_push_rss_config = efx_port_dummy_op_void,
.rx_probe = efx_farch_rx_probe,
.rx_init = efx_farch_rx_init,
.rx_remove = efx_farch_rx_remove,
......@@ -2798,7 +2814,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
.tx_init = efx_farch_tx_init,
.tx_remove = efx_farch_tx_remove,
.tx_write = efx_farch_tx_write,
.rx_push_indir_table = efx_farch_rx_push_indir_table,
.rx_push_rss_config = falcon_b0_rx_push_rss_config,
.rx_probe = efx_farch_rx_probe,
.rx_init = efx_farch_rx_init,
.rx_remove = efx_farch_rx_remove,
......
......@@ -1618,8 +1618,7 @@ void efx_farch_rx_push_indir_table(struct efx_nic *efx)
size_t i = 0;
efx_dword_t dword;
if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
return;
BUG_ON(efx_nic_rev(efx) < EFX_REV_FALCON_B0);
BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
FR_BZ_RX_INDIRECTION_TBL_ROWS);
......@@ -1745,8 +1744,6 @@ void efx_farch_init_common(struct efx_nic *efx)
EFX_INVERT_OWORD(temp);
efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER);
efx_farch_rx_push_indir_table(efx);
/* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
* controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
*/
......@@ -2187,14 +2184,14 @@ efx_farch_filter_to_gen_spec(struct efx_filter_spec *gen_spec,
}
static void
efx_farch_filter_init_rx_for_stack(struct efx_nic *efx,
struct efx_farch_filter_spec *spec)
efx_farch_filter_init_rx_auto(struct efx_nic *efx,
struct efx_farch_filter_spec *spec)
{
/* If there's only one channel then disable RSS for non VF
* traffic, thereby allowing VFs to use RSS when the PF can't.
*/
spec->priority = EFX_FILTER_PRI_REQUIRED;
spec->flags = (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_STACK |
spec->priority = EFX_FILTER_PRI_AUTO;
spec->flags = (EFX_FILTER_FLAG_RX |
(efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) |
(efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0));
spec->dmaq_id = 0;
......@@ -2459,20 +2456,13 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
rc = -EEXIST;
goto out;
}
if (spec.priority < saved_spec->priority &&
!(saved_spec->priority == EFX_FILTER_PRI_REQUIRED &&
saved_spec->flags & EFX_FILTER_FLAG_RX_STACK)) {
if (spec.priority < saved_spec->priority) {
rc = -EPERM;
goto out;
}
if (spec.flags & EFX_FILTER_FLAG_RX_STACK) {
/* Just make sure it won't be removed */
saved_spec->flags |= EFX_FILTER_FLAG_RX_STACK;
rc = 0;
goto out;
}
/* Retain the RX_STACK flag */
spec.flags |= saved_spec->flags & EFX_FILTER_FLAG_RX_STACK;
if (saved_spec->priority == EFX_FILTER_PRI_AUTO ||
saved_spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO)
spec.flags |= EFX_FILTER_FLAG_RX_OVER_AUTO;
}
/* Insert the filter */
......@@ -2553,11 +2543,11 @@ static int efx_farch_filter_remove(struct efx_nic *efx,
struct efx_farch_filter_spec *spec = &table->spec[filter_idx];
if (!test_bit(filter_idx, table->used_bitmap) ||
spec->priority > priority)
spec->priority != priority)
return -ENOENT;
if (spec->flags & EFX_FILTER_FLAG_RX_STACK) {
efx_farch_filter_init_rx_for_stack(efx, spec);
if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) {
efx_farch_filter_init_rx_auto(efx, spec);
efx_farch_filter_push_rx_config(efx);
} else {
efx_farch_filter_table_clear_entry(efx, table, filter_idx);
......@@ -2640,12 +2630,15 @@ efx_farch_filter_table_clear(struct efx_nic *efx,
unsigned int filter_idx;
spin_lock_bh(&efx->filter_lock);
for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
efx_farch_filter_remove(efx, table, filter_idx, priority);
for (filter_idx = 0; filter_idx < table->size; ++filter_idx) {
if (table->spec[filter_idx].priority != EFX_FILTER_PRI_AUTO)
efx_farch_filter_remove(efx, table,
filter_idx, priority);
}
spin_unlock_bh(&efx->filter_lock);
}
void efx_farch_filter_clear_rx(struct efx_nic *efx,
int efx_farch_filter_clear_rx(struct efx_nic *efx,
enum efx_filter_priority priority)
{
efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_IP,
......@@ -2654,6 +2647,7 @@ void efx_farch_filter_clear_rx(struct efx_nic *efx,
priority);
efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_DEF,
priority);
return 0;
}
u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
......@@ -2822,7 +2816,7 @@ int efx_farch_filter_table_probe(struct efx_nic *efx)
for (i = 0; i < EFX_FARCH_FILTER_SIZE_RX_DEF; i++) {
spec = &table->spec[i];
spec->type = EFX_FARCH_FILTER_UC_DEF + i;
efx_farch_filter_init_rx_for_stack(efx, spec);
efx_farch_filter_init_rx_auto(efx, spec);
__set_bit(i, table->used_bitmap);
}
}
......
......@@ -59,12 +59,16 @@ enum efx_filter_match_flags {
/**
* enum efx_filter_priority - priority of a hardware filter specification
* @EFX_FILTER_PRI_HINT: Performance hint
* @EFX_FILTER_PRI_AUTO: Automatic filter based on device address list
* or hardware requirements. This may only be used by the filter
* implementation for each NIC type.
* @EFX_FILTER_PRI_MANUAL: Manually configured filter
* @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level
* networking and SR-IOV)
*/
enum efx_filter_priority {
EFX_FILTER_PRI_HINT = 0,
EFX_FILTER_PRI_AUTO,
EFX_FILTER_PRI_MANUAL,
EFX_FILTER_PRI_REQUIRED,
};
......@@ -78,19 +82,18 @@ enum efx_filter_priority {
* according to the indirection table.
* @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving
* queue.
* @EFX_FILTER_FLAG_RX_STACK: Indicates a filter inserted for the
* network stack. The filter must have a priority of
* %EFX_FILTER_PRI_REQUIRED. It can be steered by a replacement
* request with priority %EFX_FILTER_PRI_MANUAL, and a removal
* request with priority %EFX_FILTER_PRI_MANUAL will reset the
* steering (but not remove the filter).
* @EFX_FILTER_FLAG_RX_OVER_AUTO: Indicates a filter that is
* overriding an automatic filter (priority
* %EFX_FILTER_PRI_AUTO). This may only be set by the filter
* implementation for each type. A removal request will restore
* the automatic filter in its place.
* @EFX_FILTER_FLAG_RX: Filter is for RX
* @EFX_FILTER_FLAG_TX: Filter is for TX
*/
enum efx_filter_flags {
EFX_FILTER_FLAG_RX_RSS = 0x01,
EFX_FILTER_FLAG_RX_SCATTER = 0x02,
EFX_FILTER_FLAG_RX_STACK = 0x04,
EFX_FILTER_FLAG_RX_OVER_AUTO = 0x04,
EFX_FILTER_FLAG_RX = 0x08,
EFX_FILTER_FLAG_TX = 0x10,
};
......
......@@ -288,12 +288,9 @@ struct efx_rx_buffer {
* Used to facilitate sharing dma mappings between recycled rx buffers
* and those passed up to the kernel.
*
* @refcnt: Number of struct efx_rx_buffer's referencing this page.
* When refcnt falls to zero, the page is unmapped for dma
* @dma_addr: The dma address of this page.
*/
struct efx_rx_page_state {
unsigned refcnt;
dma_addr_t dma_addr;
unsigned int __pad[0] ____cacheline_aligned;
......@@ -363,12 +360,6 @@ struct efx_rx_queue {
unsigned int slow_fill_count;
};
enum efx_rx_alloc_method {
RX_ALLOC_METHOD_AUTO = 0,
RX_ALLOC_METHOD_SKB = 1,
RX_ALLOC_METHOD_PAGE = 2,
};
enum efx_sync_events_state {
SYNC_EVENTS_DISABLED = 0,
SYNC_EVENTS_QUIESCENT,
......@@ -1024,7 +1015,7 @@ struct efx_mtd_partition {
* @tx_init: Initialise TX queue on the NIC
* @tx_remove: Free resources for TX queue
* @tx_write: Write TX descriptors and doorbell
* @rx_push_indir_table: Write RSS indirection table to the NIC
* @rx_push_rss_config: Write RSS hash key and indirection table to the NIC
* @rx_probe: Allocate resources for RX queue
* @rx_init: Initialise RX queue on the NIC
* @rx_remove: Free resources for RX queue
......@@ -1044,7 +1035,8 @@ struct efx_mtd_partition {
* @filter_insert: add or replace a filter
* @filter_remove_safe: remove a filter by ID, carefully
* @filter_get_safe: retrieve a filter by ID, carefully
* @filter_clear_rx: remove RX filters by priority
* @filter_clear_rx: Remove all RX filters whose priority is less than or
* equal to the given priority and is not %EFX_FILTER_PRI_AUTO
* @filter_count_rx_used: Get the number of filters in use at a given priority
* @filter_get_rx_id_limit: Get maximum value of a filter id, plus 1
* @filter_get_rx_ids: Get list of RX filters at a given priority
......@@ -1141,7 +1133,7 @@ struct efx_nic_type {
void (*tx_init)(struct efx_tx_queue *tx_queue);
void (*tx_remove)(struct efx_tx_queue *tx_queue);
void (*tx_write)(struct efx_tx_queue *tx_queue);
void (*rx_push_indir_table)(struct efx_nic *efx);
void (*rx_push_rss_config)(struct efx_nic *efx);
int (*rx_probe)(struct efx_rx_queue *rx_queue);
void (*rx_init)(struct efx_rx_queue *rx_queue);
void (*rx_remove)(struct efx_rx_queue *rx_queue);
......@@ -1166,8 +1158,8 @@ struct efx_nic_type {
int (*filter_get_safe)(struct efx_nic *efx,
enum efx_filter_priority priority,
u32 filter_id, struct efx_filter_spec *);
void (*filter_clear_rx)(struct efx_nic *efx,
enum efx_filter_priority priority);
int (*filter_clear_rx)(struct efx_nic *efx,
enum efx_filter_priority priority);
u32 (*filter_count_rx_used)(struct efx_nic *efx,
enum efx_filter_priority priority);
u32 (*filter_get_rx_id_limit)(struct efx_nic *efx);
......
......@@ -412,8 +412,8 @@ enum {
EF10_STAT_rx_dp_q_disabled_packets,
EF10_STAT_rx_dp_di_dropped_packets,
EF10_STAT_rx_dp_streaming_packets,
EF10_STAT_rx_dp_emerg_fetch,
EF10_STAT_rx_dp_emerg_wait,
EF10_STAT_rx_dp_hlb_fetch,
EF10_STAT_rx_dp_hlb_wait,
EF10_STAT_COUNT
};
......@@ -566,6 +566,8 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
unsigned int new_mode);
int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings);
size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats);
void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev);
void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
struct sk_buff *skb);
......@@ -693,8 +695,8 @@ int efx_farch_filter_remove_safe(struct efx_nic *efx,
int efx_farch_filter_get_safe(struct efx_nic *efx,
enum efx_filter_priority priority, u32 filter_id,
struct efx_filter_spec *);
void efx_farch_filter_clear_rx(struct efx_nic *efx,
enum efx_filter_priority priority);
int efx_farch_filter_clear_rx(struct efx_nic *efx,
enum efx_filter_priority priority);
u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
enum efx_filter_priority priority);
u32 efx_farch_filter_get_rx_id_limit(struct efx_nic *efx);
......@@ -762,10 +764,6 @@ int falcon_reset_xaui(struct efx_nic *efx);
void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
void efx_farch_init_common(struct efx_nic *efx);
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);
}
void efx_farch_rx_push_indir_table(struct efx_nic *efx);
int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
......
......@@ -255,6 +255,15 @@ struct efx_ptp_timeset {
* @nic_ts_enabled: Flag indicating if NIC generated TS events are handled
* @txbuf: Buffer for use when transmitting (PTP) packets to MC (avoids
* allocations in main data path).
* @good_syncs: Number of successful synchronisations.
* @fast_syncs: Number of synchronisations requiring short delay
* @bad_syncs: Number of failed synchronisations.
* @sync_timeouts: Number of synchronisation timeouts
* @no_time_syncs: Number of synchronisations with no good times.
* @invalid_sync_windows: Number of sync windows with bad durations.
* @undersize_sync_windows: Number of corrected sync windows that are too small
* @oversize_sync_windows: Number of corrected sync windows that are too large
* @rx_no_timestamp: Number of packets received without a timestamp.
* @timeset: Last set of synchronisation statistics.
*/
struct efx_ptp_data {
......@@ -300,6 +309,16 @@ struct efx_ptp_data {
struct workqueue_struct *pps_workwq;
bool nic_ts_enabled;
MCDI_DECLARE_BUF(txbuf, MC_CMD_PTP_IN_TRANSMIT_LENMAX);
unsigned int good_syncs;
unsigned int fast_syncs;
unsigned int bad_syncs;
unsigned int sync_timeouts;
unsigned int no_time_syncs;
unsigned int invalid_sync_windows;
unsigned int undersize_sync_windows;
unsigned int oversize_sync_windows;
unsigned int rx_no_timestamp;
struct efx_ptp_timeset
timeset[MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM];
};
......@@ -312,6 +331,78 @@ static int efx_phc_settime(struct ptp_clock_info *ptp,
static int efx_phc_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *request, int on);
#define PTP_SW_STAT(ext_name, field_name) \
{ #ext_name, 0, offsetof(struct efx_ptp_data, field_name) }
#define PTP_MC_STAT(ext_name, mcdi_name) \
{ #ext_name, 32, MC_CMD_PTP_OUT_STATUS_STATS_ ## mcdi_name ## _OFST }
static const struct efx_hw_stat_desc efx_ptp_stat_desc[] = {
PTP_SW_STAT(ptp_good_syncs, good_syncs),
PTP_SW_STAT(ptp_fast_syncs, fast_syncs),
PTP_SW_STAT(ptp_bad_syncs, bad_syncs),
PTP_SW_STAT(ptp_sync_timeouts, sync_timeouts),
PTP_SW_STAT(ptp_no_time_syncs, no_time_syncs),
PTP_SW_STAT(ptp_invalid_sync_windows, invalid_sync_windows),
PTP_SW_STAT(ptp_undersize_sync_windows, undersize_sync_windows),
PTP_SW_STAT(ptp_oversize_sync_windows, oversize_sync_windows),
PTP_SW_STAT(ptp_rx_no_timestamp, rx_no_timestamp),
PTP_MC_STAT(ptp_tx_timestamp_packets, TX),
PTP_MC_STAT(ptp_rx_timestamp_packets, RX),
PTP_MC_STAT(ptp_timestamp_packets, TS),
PTP_MC_STAT(ptp_filter_matches, FM),
PTP_MC_STAT(ptp_non_filter_matches, NFM),
};
#define PTP_STAT_COUNT ARRAY_SIZE(efx_ptp_stat_desc)
static const unsigned long efx_ptp_stat_mask[] = {
[0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL,
};
size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings)
{
if (!efx->ptp_data)
return 0;
return efx_nic_describe_stats(efx_ptp_stat_desc, PTP_STAT_COUNT,
efx_ptp_stat_mask, strings);
}
size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_STATUS_LEN);
MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_STATUS_LEN);
size_t i;
int rc;
if (!efx->ptp_data)
return 0;
/* Copy software statistics */
for (i = 0; i < PTP_STAT_COUNT; i++) {
if (efx_ptp_stat_desc[i].dma_width)
continue;
stats[i] = *(unsigned int *)((char *)efx->ptp_data +
efx_ptp_stat_desc[i].offset);
}
/* Fetch MC statistics. We *must* fill in all statistics or
* risk leaking kernel memory to userland, so if the MCDI
* request fails we pretend we got zeroes.
*/
MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_STATUS);
MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
outbuf, sizeof(outbuf), NULL);
if (rc) {
netif_err(efx, hw, efx->net_dev,
"MC_CMD_PTP_OP_STATUS failed (%d)\n", rc);
memset(outbuf, 0, sizeof(outbuf));
}
efx_nic_update_stats(efx_ptp_stat_desc, PTP_STAT_COUNT,
efx_ptp_stat_mask,
stats, _MCDI_PTR(outbuf, 0), false);
return PTP_STAT_COUNT;
}
/* For Siena platforms NIC time is s and ns */
static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor)
{
......@@ -633,7 +724,8 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
/* Read the set of results and find the last good host-MC
* synchronization result. The MC times when it finishes reading the
* host time so the corrected window time should be fairly constant
* for a given platform.
* for a given platform. Increment stats for any results that appear
* to be erroneous.
*/
for (i = 0; i < number_readings; i++) {
s32 window, corrected;
......@@ -658,9 +750,13 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
* interrupt or other delay occurred between reading the system
* time and writing it to MC memory.
*/
if (window >= SYNCHRONISATION_GRANULARITY_NS &&
corrected < MAX_SYNCHRONISATION_NS &&
corrected >= ptp->min_synchronisation_ns) {
if (window < SYNCHRONISATION_GRANULARITY_NS) {
++ptp->invalid_sync_windows;
} else if (corrected >= MAX_SYNCHRONISATION_NS) {
++ptp->undersize_sync_windows;
} else if (corrected < ptp->min_synchronisation_ns) {
++ptp->oversize_sync_windows;
} else {
ngood++;
last_good = i;
}
......@@ -741,6 +837,11 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
loops++;
}
if (loops <= 1)
++ptp->fast_syncs;
if (!time_before(jiffies, timeout))
++ptp->sync_timeouts;
if (ACCESS_ONCE(*start))
efx_ptp_send_times(efx, &last_time);
......@@ -749,9 +850,20 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
MC_CMD_PTP_IN_SYNCHRONIZE_LEN,
synch_buf, sizeof(synch_buf),
&response_length);
if (rc == 0)
if (rc == 0) {
rc = efx_ptp_process_times(efx, synch_buf, response_length,
&last_time);
if (rc == 0)
++ptp->good_syncs;
else
++ptp->no_time_syncs;
}
/* Increment the bad syncs counter if the synchronize fails, whatever
* the reason.
*/
if (rc != 0)
++ptp->bad_syncs;
return rc;
}
......@@ -907,9 +1019,7 @@ static void efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q)
__skb_queue_tail(q, skb);
} else if (time_after(jiffies, match->expiry)) {
match->state = PTP_PACKET_STATE_TIMED_OUT;
if (net_ratelimit())
netif_warn(efx, rx_err, efx->net_dev,
"PTP packet - no timestamp seen\n");
++ptp->rx_no_timestamp;
__skb_queue_tail(q, skb);
} else {
/* Replace unprocessed entry and stop */
......
......@@ -321,6 +321,31 @@ static int siena_probe_nic(struct efx_nic *efx)
return rc;
}
static void siena_rx_push_rss_config(struct efx_nic *efx)
{
efx_oword_t temp;
/* Set hash key for IPv4 */
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
/* Enable IPv6 RSS */
BUILD_BUG_ON(sizeof(efx->rx_hash_key) <
2 * sizeof(temp) + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8 ||
FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN != 0);
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1);
memcpy(&temp, efx->rx_hash_key + sizeof(temp), sizeof(temp));
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2);
EFX_POPULATE_OWORD_2(temp, FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1,
FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, 1);
memcpy(&temp, efx->rx_hash_key + 2 * sizeof(temp),
FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3);
efx_farch_rx_push_indir_table(efx);
}
/* This call performs hardware-specific global initialisation, such as
* defining the descriptor cache sizes and number of RSS channels.
* It does not set up any buffers, descriptor rings or event queues.
......@@ -361,23 +386,7 @@ static int siena_init_nic(struct efx_nic *efx)
EFX_RX_USR_BUF_SIZE >> 5);
efx_writeo(efx, &temp, FR_AZ_RX_CFG);
/* Set hash key for IPv4 */
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_BZ_RX_RSS_TKEY);
/* Enable IPv6 RSS */
BUILD_BUG_ON(sizeof(efx->rx_hash_key) <
2 * sizeof(temp) + FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8 ||
FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN != 0);
memcpy(&temp, efx->rx_hash_key, sizeof(temp));
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG1);
memcpy(&temp, efx->rx_hash_key + sizeof(temp), sizeof(temp));
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG2);
EFX_POPULATE_OWORD_2(temp, FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1,
FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, 1);
memcpy(&temp, efx->rx_hash_key + 2 * sizeof(temp),
FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);
efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3);
siena_rx_push_rss_config(efx);
/* Enable event logging */
rc = efx_mcdi_log_ctrl(efx, true, false, 0);
......@@ -940,7 +949,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.tx_init = efx_farch_tx_init,
.tx_remove = efx_farch_tx_remove,
.tx_write = efx_farch_tx_write,
.rx_push_indir_table = efx_farch_rx_push_indir_table,
.rx_push_rss_config = siena_rx_push_rss_config,
.rx_probe = efx_farch_rx_probe,
.rx_init = efx_farch_rx_init,
.rx_remove = efx_farch_rx_remove,
......
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