mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-25 12:04:46 +08:00
sfc: add ef100 MAE counter support functions
Start and stop MAE counter streaming, and grant credits. Signed-off-by: Edward Cree <ecree.xilinx@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
36df6136a7
commit
e5731274cd
@ -112,6 +112,117 @@ int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efx_mae_start_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue)
|
||||
{
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN);
|
||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
|
||||
u32 out_flags;
|
||||
size_t outlen;
|
||||
int rc;
|
||||
|
||||
MCDI_SET_WORD(inbuf, MAE_COUNTERS_STREAM_START_V2_IN_QID,
|
||||
efx_rx_queue_index(rx_queue));
|
||||
MCDI_SET_WORD(inbuf, MAE_COUNTERS_STREAM_START_V2_IN_PACKET_SIZE,
|
||||
efx->net_dev->mtu);
|
||||
MCDI_SET_DWORD(inbuf, MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
|
||||
BIT(MAE_COUNTER_TYPE_AR) | BIT(MAE_COUNTER_TYPE_CT) |
|
||||
BIT(MAE_COUNTER_TYPE_OR));
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_COUNTERS_STREAM_START,
|
||||
inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (outlen < sizeof(outbuf))
|
||||
return -EIO;
|
||||
out_flags = MCDI_DWORD(outbuf, MAE_COUNTERS_STREAM_START_OUT_FLAGS);
|
||||
if (out_flags & BIT(MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_OFST)) {
|
||||
netif_dbg(efx, drv, efx->net_dev,
|
||||
"MAE counter stream uses credits\n");
|
||||
rx_queue->grant_credits = true;
|
||||
out_flags &= ~BIT(MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_OFST);
|
||||
}
|
||||
if (out_flags) {
|
||||
netif_err(efx, drv, efx->net_dev,
|
||||
"MAE counter stream start: unrecognised flags %x\n",
|
||||
out_flags);
|
||||
goto out_stop;
|
||||
}
|
||||
return 0;
|
||||
out_stop:
|
||||
efx_mae_stop_counters(efx, rx_queue);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static bool efx_mae_counters_flushed(u32 *flush_gen, u32 *seen_gen)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EFX_TC_COUNTER_TYPE_MAX; i++)
|
||||
if ((s32)(flush_gen[i] - seen_gen[i]) > 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int efx_mae_stop_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue)
|
||||
{
|
||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_LENMAX);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN);
|
||||
size_t outlen;
|
||||
int rc, i;
|
||||
|
||||
MCDI_SET_WORD(inbuf, MAE_COUNTERS_STREAM_STOP_IN_QID,
|
||||
efx_rx_queue_index(rx_queue));
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_COUNTERS_STREAM_STOP,
|
||||
inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
netif_dbg(efx, drv, efx->net_dev, "Draining counters:\n");
|
||||
/* Only process received generation counts */
|
||||
for (i = 0; (i < (outlen / 4)) && (i < EFX_TC_COUNTER_TYPE_MAX); i++) {
|
||||
efx->tc->flush_gen[i] = MCDI_ARRAY_DWORD(outbuf,
|
||||
MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT,
|
||||
i);
|
||||
netif_dbg(efx, drv, efx->net_dev,
|
||||
"\ttype %u, awaiting gen %u\n", i,
|
||||
efx->tc->flush_gen[i]);
|
||||
}
|
||||
|
||||
efx->tc->flush_counters = true;
|
||||
|
||||
/* Drain can take up to 2 seconds owing to FWRIVERHD-2884; whatever
|
||||
* timeout we use, that delay is added to unload on nonresponsive
|
||||
* hardware, so 2500ms seems like a reasonable compromise.
|
||||
*/
|
||||
if (!wait_event_timeout(efx->tc->flush_wq,
|
||||
efx_mae_counters_flushed(efx->tc->flush_gen,
|
||||
efx->tc->seen_gen),
|
||||
msecs_to_jiffies(2500)))
|
||||
netif_warn(efx, drv, efx->net_dev,
|
||||
"Failed to drain counters RXQ, FW may be unhappy\n");
|
||||
|
||||
efx->tc->flush_counters = false;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void efx_mae_counters_grant_credits(struct work_struct *work)
|
||||
{
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN);
|
||||
struct efx_rx_queue *rx_queue = container_of(work, struct efx_rx_queue,
|
||||
grant_work);
|
||||
struct efx_nic *efx = rx_queue->efx;
|
||||
unsigned int credits;
|
||||
|
||||
BUILD_BUG_ON(MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN);
|
||||
credits = READ_ONCE(rx_queue->notified_count) - rx_queue->granted_count;
|
||||
MCDI_SET_DWORD(inbuf, MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS,
|
||||
credits);
|
||||
if (!efx_mcdi_rpc(efx, MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS,
|
||||
inbuf, sizeof(inbuf), NULL, 0, NULL))
|
||||
rx_queue->granted_count += credits;
|
||||
}
|
||||
|
||||
static int efx_mae_get_basic_caps(struct efx_nic *efx, struct mae_caps *caps)
|
||||
{
|
||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_CAPS_OUT_LEN);
|
||||
|
@ -27,6 +27,10 @@ void efx_mae_mport_mport(struct efx_nic *efx, u32 mport_id, u32 *out);
|
||||
|
||||
int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id);
|
||||
|
||||
int efx_mae_start_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue);
|
||||
int efx_mae_stop_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue);
|
||||
void efx_mae_counters_grant_credits(struct work_struct *work);
|
||||
|
||||
#define MAE_NUM_FIELDS (MAE_FIELD_ENC_VNET_ID + 1)
|
||||
|
||||
struct mae_caps {
|
||||
|
@ -221,6 +221,11 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
|
||||
#define MCDI_BYTE(_buf, _field) \
|
||||
((void)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 1), \
|
||||
*MCDI_PTR(_buf, _field))
|
||||
#define MCDI_SET_WORD(_buf, _field, _value) do { \
|
||||
BUILD_BUG_ON(MC_CMD_ ## _field ## _LEN != 2); \
|
||||
BUILD_BUG_ON(MC_CMD_ ## _field ## _OFST & 1); \
|
||||
*(__force __le16 *)MCDI_PTR(_buf, _field) = cpu_to_le16(_value);\
|
||||
} while (0)
|
||||
#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)))
|
||||
|
@ -751,6 +751,7 @@ int efx_init_struct_tc(struct efx_nic *efx)
|
||||
INIT_LIST_HEAD(&efx->tc->block_list);
|
||||
|
||||
mutex_init(&efx->tc->mutex);
|
||||
init_waitqueue_head(&efx->tc->flush_wq);
|
||||
rc = rhashtable_init(&efx->tc->match_action_ht, &efx_tc_match_action_ht_params);
|
||||
if (rc < 0)
|
||||
goto fail_match_action_ht;
|
||||
|
@ -14,6 +14,14 @@
|
||||
#include <net/flow_offload.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include "net_driver.h"
|
||||
#include "mcdi_pcol.h" /* for MAE_COUNTER_TYPE_* */
|
||||
|
||||
enum efx_tc_counter_type {
|
||||
EFX_TC_COUNTER_TYPE_AR = MAE_COUNTER_TYPE_AR,
|
||||
EFX_TC_COUNTER_TYPE_CT = MAE_COUNTER_TYPE_CT,
|
||||
EFX_TC_COUNTER_TYPE_OR = MAE_COUNTER_TYPE_OR,
|
||||
EFX_TC_COUNTER_TYPE_MAX
|
||||
};
|
||||
|
||||
#define IS_ALL_ONES(v) (!(typeof (v))~(v))
|
||||
|
||||
@ -79,6 +87,12 @@ enum efx_tc_rule_prios {
|
||||
* @reps_filter_uc: VNIC filter for representor unicast RX (promisc)
|
||||
* @reps_filter_mc: VNIC filter for representor multicast RX (allmulti)
|
||||
* @reps_mport_vport_id: vport_id for representor RX filters
|
||||
* @flush_counters: counters have been stopped, waiting for drain
|
||||
* @flush_gen: final generation count per type array as reported by
|
||||
* MC_CMD_MAE_COUNTERS_STREAM_STOP
|
||||
* @seen_gen: most recent generation count per type as seen by efx_tc_rx()
|
||||
* @flush_wq: wait queue used by efx_mae_stop_counters() to wait for
|
||||
* MAE counters RXQ to finish draining
|
||||
* @dflt: Match-action rules for default switching; at priority
|
||||
* %EFX_TC_PRIO_DFLT. Named by *ingress* port
|
||||
* @dflt.pf: rule for traffic ingressing from PF (egresses to wire)
|
||||
@ -92,6 +106,10 @@ struct efx_tc_state {
|
||||
struct rhashtable match_action_ht;
|
||||
u32 reps_mport_id, reps_mport_vport_id;
|
||||
s32 reps_filter_uc, reps_filter_mc;
|
||||
bool flush_counters;
|
||||
u32 flush_gen[EFX_TC_COUNTER_TYPE_MAX];
|
||||
u32 seen_gen[EFX_TC_COUNTER_TYPE_MAX];
|
||||
wait_queue_head_t flush_wq;
|
||||
struct {
|
||||
struct efx_tc_flow_rule pf;
|
||||
struct efx_tc_flow_rule wire;
|
||||
|
Loading…
Reference in New Issue
Block a user