sfc: enumerate mports in ef100
MAE ports (mports) are the ports on the EF100 embedded switch such as networking PCIe functions, the physical port, and potentially others. Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com> Acked-by: Martin Habets <habetsm.xilinx@gmail.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
14743ddd24
commit
a6a15aca42
@ -747,6 +747,19 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
|
||||
id);
|
||||
nic_data->base_mport = id;
|
||||
nic_data->have_mport = true;
|
||||
|
||||
/* Construct mport selector for "calling PF" */
|
||||
efx_mae_mport_uplink(efx, &selector);
|
||||
/* Look up actual mport ID */
|
||||
rc = efx_mae_lookup_mport(efx, selector, &id);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (id >> 16)
|
||||
netif_warn(efx, probe, efx->net_dev, "Bad own m-port id %#x\n",
|
||||
id);
|
||||
nic_data->own_mport = id;
|
||||
nic_data->have_own_mport = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -1126,6 +1139,14 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
|
||||
rc);
|
||||
}
|
||||
|
||||
rc = efx_init_mae(efx);
|
||||
if (rc)
|
||||
netif_warn(efx, probe, net_dev,
|
||||
"Failed to init MAE rc %d; representors will not function\n",
|
||||
rc);
|
||||
else
|
||||
efx_ef100_init_reps(efx);
|
||||
|
||||
rc = efx_init_tc(efx);
|
||||
if (rc) {
|
||||
/* Either we don't have an MAE at all (i.e. legacy v-switching),
|
||||
@ -1157,6 +1178,12 @@ void ef100_remove(struct efx_nic *efx)
|
||||
{
|
||||
struct ef100_nic_data *nic_data = efx->nic_data;
|
||||
|
||||
#ifdef CONFIG_SFC_SRIOV
|
||||
if (efx->mae) {
|
||||
efx_ef100_fini_reps(efx);
|
||||
efx_fini_mae(efx);
|
||||
}
|
||||
#endif
|
||||
efx_mcdi_detach(efx);
|
||||
efx_mcdi_fini(efx);
|
||||
if (nic_data)
|
||||
|
@ -74,6 +74,10 @@ struct ef100_nic_data {
|
||||
u64 stats[EF100_STAT_COUNT];
|
||||
u32 base_mport;
|
||||
bool have_mport; /* base_mport was populated successfully */
|
||||
u32 own_mport;
|
||||
u32 local_mae_intf; /* interface_idx that corresponds to us, in mport enumerate */
|
||||
bool have_own_mport; /* own_mport was populated successfully */
|
||||
bool have_local_intf; /* local_mae_intf was populated successfully */
|
||||
bool grp_mae; /* MAE Privilege */
|
||||
u16 tso_max_hdr_len;
|
||||
u16 tso_max_payload_num_segs;
|
||||
|
@ -9,6 +9,7 @@
|
||||
* by the Free Software Foundation, incorporated herein by reference.
|
||||
*/
|
||||
|
||||
#include <linux/rhashtable.h>
|
||||
#include "ef100_rep.h"
|
||||
#include "ef100_netdev.h"
|
||||
#include "ef100_nic.h"
|
||||
@ -341,6 +342,27 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)
|
||||
efx_ef100_vfrep_destroy(efx, efv);
|
||||
}
|
||||
|
||||
void efx_ef100_init_reps(struct efx_nic *efx)
|
||||
{
|
||||
struct ef100_nic_data *nic_data = efx->nic_data;
|
||||
int rc;
|
||||
|
||||
nic_data->have_local_intf = false;
|
||||
rc = efx_mae_enumerate_mports(efx);
|
||||
if (rc)
|
||||
pci_warn(efx->pci_dev,
|
||||
"Could not enumerate mports (rc=%d), are we admin?",
|
||||
rc);
|
||||
}
|
||||
|
||||
void efx_ef100_fini_reps(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mae *mae = efx->mae;
|
||||
|
||||
rhashtable_free_and_destroy(&mae->mports_ht, efx_mae_remove_mport,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int efx_ef100_rep_poll(struct napi_struct *napi, int weight)
|
||||
{
|
||||
struct efx_rep *efv = container_of(napi, struct efx_rep, napi);
|
||||
|
@ -67,4 +67,6 @@ void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf);
|
||||
*/
|
||||
struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
|
||||
extern const struct net_device_ops efx_ef100_rep_netdev_ops;
|
||||
void efx_ef100_init_reps(struct efx_nic *efx);
|
||||
void efx_ef100_fini_reps(struct efx_nic *efx);
|
||||
#endif /* EF100_REP_H */
|
||||
|
@ -9,8 +9,11 @@
|
||||
* by the Free Software Foundation, incorporated herein by reference.
|
||||
*/
|
||||
|
||||
#include <linux/rhashtable.h>
|
||||
#include "ef100_nic.h"
|
||||
#include "mae.h"
|
||||
#include "mcdi.h"
|
||||
#include "mcdi_pcol.h"
|
||||
#include "mcdi_pcol_mae.h"
|
||||
|
||||
int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
|
||||
@ -490,6 +493,163 @@ static bool efx_mae_asl_id(u32 id)
|
||||
return !!(id & BIT(31));
|
||||
}
|
||||
|
||||
/* mport handling */
|
||||
static const struct rhashtable_params efx_mae_mports_ht_params = {
|
||||
.key_len = sizeof(u32),
|
||||
.key_offset = offsetof(struct mae_mport_desc, mport_id),
|
||||
.head_offset = offsetof(struct mae_mport_desc, linkage),
|
||||
};
|
||||
|
||||
struct mae_mport_desc *efx_mae_get_mport(struct efx_nic *efx, u32 mport_id)
|
||||
{
|
||||
return rhashtable_lookup_fast(&efx->mae->mports_ht, &mport_id,
|
||||
efx_mae_mports_ht_params);
|
||||
}
|
||||
|
||||
static int efx_mae_add_mport(struct efx_nic *efx, struct mae_mport_desc *desc)
|
||||
{
|
||||
struct efx_mae *mae = efx->mae;
|
||||
int rc;
|
||||
|
||||
rc = rhashtable_insert_fast(&mae->mports_ht, &desc->linkage,
|
||||
efx_mae_mports_ht_params);
|
||||
|
||||
if (rc) {
|
||||
pci_err(efx->pci_dev, "Failed to insert MPORT %08x, rc %d\n",
|
||||
desc->mport_id, rc);
|
||||
kfree(desc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void efx_mae_remove_mport(void *desc, void *arg)
|
||||
{
|
||||
struct mae_mport_desc *mport = desc;
|
||||
|
||||
synchronize_rcu();
|
||||
kfree(mport);
|
||||
}
|
||||
|
||||
static int efx_mae_process_mport(struct efx_nic *efx,
|
||||
struct mae_mport_desc *desc)
|
||||
{
|
||||
struct ef100_nic_data *nic_data = efx->nic_data;
|
||||
struct mae_mport_desc *mport;
|
||||
|
||||
mport = efx_mae_get_mport(efx, desc->mport_id);
|
||||
if (!IS_ERR_OR_NULL(mport)) {
|
||||
netif_err(efx, drv, efx->net_dev,
|
||||
"mport with id %u does exist!!!\n", desc->mport_id);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (nic_data->have_own_mport &&
|
||||
desc->mport_id == nic_data->own_mport) {
|
||||
WARN_ON(desc->mport_type != MAE_MPORT_DESC_MPORT_TYPE_VNIC);
|
||||
WARN_ON(desc->vnic_client_type !=
|
||||
MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION);
|
||||
nic_data->local_mae_intf = desc->interface_idx;
|
||||
nic_data->have_local_intf = true;
|
||||
pci_dbg(efx->pci_dev, "MAE interface_idx is %u\n",
|
||||
nic_data->local_mae_intf);
|
||||
}
|
||||
|
||||
return efx_mae_add_mport(efx, desc);
|
||||
}
|
||||
|
||||
#define MCDI_MPORT_JOURNAL_LEN \
|
||||
ALIGN(MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2, 4)
|
||||
|
||||
int efx_mae_enumerate_mports(struct efx_nic *efx)
|
||||
{
|
||||
efx_dword_t *outbuf = kzalloc(MCDI_MPORT_JOURNAL_LEN, GFP_KERNEL);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN);
|
||||
MCDI_DECLARE_STRUCT_PTR(desc);
|
||||
size_t outlen, stride, count;
|
||||
int rc = 0, i;
|
||||
|
||||
if (!outbuf)
|
||||
return -ENOMEM;
|
||||
do {
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_READ_JOURNAL, inbuf,
|
||||
sizeof(inbuf), outbuf,
|
||||
MCDI_MPORT_JOURNAL_LEN, &outlen);
|
||||
if (rc)
|
||||
goto fail;
|
||||
if (outlen < MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_OFST) {
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
count = MCDI_DWORD(outbuf, MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT);
|
||||
if (!count)
|
||||
continue; /* not break; we want to look at MORE flag */
|
||||
stride = MCDI_DWORD(outbuf, MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC);
|
||||
if (stride < MAE_MPORT_DESC_LEN) {
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
if (outlen < MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LEN(count * stride)) {
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct mae_mport_desc *d;
|
||||
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
desc = (efx_dword_t *)
|
||||
_MCDI_PTR(outbuf, MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_OFST +
|
||||
i * stride);
|
||||
d->mport_id = MCDI_STRUCT_DWORD(desc, MAE_MPORT_DESC_MPORT_ID);
|
||||
d->flags = MCDI_STRUCT_DWORD(desc, MAE_MPORT_DESC_FLAGS);
|
||||
d->caller_flags = MCDI_STRUCT_DWORD(desc,
|
||||
MAE_MPORT_DESC_CALLER_FLAGS);
|
||||
d->mport_type = MCDI_STRUCT_DWORD(desc,
|
||||
MAE_MPORT_DESC_MPORT_TYPE);
|
||||
switch (d->mport_type) {
|
||||
case MAE_MPORT_DESC_MPORT_TYPE_NET_PORT:
|
||||
d->port_idx = MCDI_STRUCT_DWORD(desc,
|
||||
MAE_MPORT_DESC_NET_PORT_IDX);
|
||||
break;
|
||||
case MAE_MPORT_DESC_MPORT_TYPE_ALIAS:
|
||||
d->alias_mport_id = MCDI_STRUCT_DWORD(desc,
|
||||
MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID);
|
||||
break;
|
||||
case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
|
||||
d->vnic_client_type = MCDI_STRUCT_DWORD(desc,
|
||||
MAE_MPORT_DESC_VNIC_CLIENT_TYPE);
|
||||
d->interface_idx = MCDI_STRUCT_DWORD(desc,
|
||||
MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE);
|
||||
d->pf_idx = MCDI_STRUCT_WORD(desc,
|
||||
MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX);
|
||||
d->vf_idx = MCDI_STRUCT_WORD(desc,
|
||||
MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX);
|
||||
break;
|
||||
default:
|
||||
/* Unknown mport_type, just accept it */
|
||||
break;
|
||||
}
|
||||
rc = efx_mae_process_mport(efx, d);
|
||||
/* Any failure will be due to memory allocation faiure,
|
||||
* so there is no point to try subsequent entries.
|
||||
*/
|
||||
if (rc)
|
||||
goto fail;
|
||||
}
|
||||
} while (MCDI_FIELD(outbuf, MAE_MPORT_READ_JOURNAL_OUT, MORE) &&
|
||||
!WARN_ON(!count));
|
||||
fail:
|
||||
kfree(outbuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
|
||||
{
|
||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
|
||||
@ -805,3 +965,34 @@ int efx_mae_delete_rule(struct efx_nic *efx, u32 id)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int efx_init_mae(struct efx_nic *efx)
|
||||
{
|
||||
struct ef100_nic_data *nic_data = efx->nic_data;
|
||||
struct efx_mae *mae;
|
||||
int rc;
|
||||
|
||||
if (!nic_data->have_mport)
|
||||
return -EINVAL;
|
||||
|
||||
mae = kmalloc(sizeof(*mae), GFP_KERNEL);
|
||||
if (!mae)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = rhashtable_init(&mae->mports_ht, &efx_mae_mports_ht_params);
|
||||
if (rc < 0) {
|
||||
kfree(mae);
|
||||
return rc;
|
||||
}
|
||||
efx->mae = mae;
|
||||
mae->efx = efx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void efx_fini_mae(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_mae *mae = efx->mae;
|
||||
|
||||
kfree(mae);
|
||||
efx->mae = NULL;
|
||||
}
|
||||
|
@ -27,6 +27,39 @@ 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);
|
||||
|
||||
struct mae_mport_desc {
|
||||
u32 mport_id;
|
||||
u32 flags;
|
||||
u32 caller_flags; /* enum mae_mport_desc_caller_flags */
|
||||
u32 mport_type; /* MAE_MPORT_DESC_MPORT_TYPE_* */
|
||||
union {
|
||||
u32 port_idx; /* for mport_type == NET_PORT */
|
||||
u32 alias_mport_id; /* for mport_type == ALIAS */
|
||||
struct { /* for mport_type == VNIC */
|
||||
u32 vnic_client_type; /* MAE_MPORT_DESC_VNIC_CLIENT_TYPE_* */
|
||||
u32 interface_idx;
|
||||
u16 pf_idx;
|
||||
u16 vf_idx;
|
||||
};
|
||||
};
|
||||
struct rhash_head linkage;
|
||||
};
|
||||
|
||||
int efx_mae_enumerate_mports(struct efx_nic *efx);
|
||||
struct mae_mport_desc *efx_mae_get_mport(struct efx_nic *efx, u32 mport_id);
|
||||
void efx_mae_put_mport(struct efx_nic *efx, struct mae_mport_desc *desc);
|
||||
|
||||
/**
|
||||
* struct efx_mae - MAE information
|
||||
*
|
||||
* @efx: The associated NIC
|
||||
* @mports_ht: m-port descriptions from MC_CMD_MAE_MPORT_READ_JOURNAL
|
||||
*/
|
||||
struct efx_mae {
|
||||
struct efx_nic *efx;
|
||||
struct rhashtable mports_ht;
|
||||
};
|
||||
|
||||
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);
|
||||
@ -60,4 +93,7 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
|
||||
u32 prio, u32 acts_id, u32 *id);
|
||||
int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
|
||||
|
||||
int efx_init_mae(struct efx_nic *efx);
|
||||
void efx_fini_mae(struct efx_nic *efx);
|
||||
void efx_mae_remove_mport(void *desc, void *arg);
|
||||
#endif /* EF100_MAE_H */
|
||||
|
@ -229,6 +229,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
|
||||
#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_STRUCT_WORD(_buf, _field) \
|
||||
((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 2), \
|
||||
le16_to_cpu(*(__force const __le16 *)MCDI_STRUCT_PTR(_buf, _field)))
|
||||
/* Write a 16-bit field defined in the protocol as being big-endian. */
|
||||
#define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do { \
|
||||
BUILD_BUG_ON(_field ## _LEN != 2); \
|
||||
@ -241,6 +244,8 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
|
||||
EFX_POPULATE_DWORD_1(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0, _value)
|
||||
#define MCDI_DWORD(_buf, _field) \
|
||||
EFX_DWORD_FIELD(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0)
|
||||
#define MCDI_STRUCT_DWORD(_buf, _field) \
|
||||
EFX_DWORD_FIELD(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0)
|
||||
/* Write a 32-bit field defined in the protocol as being big-endian. */
|
||||
#define MCDI_STRUCT_SET_DWORD_BE(_buf, _field, _value) do { \
|
||||
BUILD_BUG_ON(_field ## _LEN != 4); \
|
||||
|
@ -845,6 +845,8 @@ enum efx_xdp_tx_queues_mode {
|
||||
EFX_XDP_TX_QUEUES_BORROWED /* queues borrowed from net stack */
|
||||
};
|
||||
|
||||
struct efx_mae;
|
||||
|
||||
/**
|
||||
* struct efx_nic - an Efx NIC
|
||||
* @name: Device name (net device name or bus id before net device registered)
|
||||
@ -881,6 +883,7 @@ enum efx_xdp_tx_queues_mode {
|
||||
* @msi_context: Context for each MSI
|
||||
* @extra_channel_types: Types of extra (non-traffic) channels that
|
||||
* should be allocated for this NIC
|
||||
* @mae: Details of the Match Action Engine
|
||||
* @xdp_tx_queue_count: Number of entries in %xdp_tx_queues.
|
||||
* @xdp_tx_queues: Array of pointers to tx queues used for XDP transmit.
|
||||
* @xdp_txq_queues_mode: XDP TX queues sharing strategy.
|
||||
@ -1044,6 +1047,7 @@ struct efx_nic {
|
||||
struct efx_msi_context msi_context[EFX_MAX_CHANNELS];
|
||||
const struct efx_channel_type *
|
||||
extra_channel_type[EFX_MAX_EXTRA_CHANNELS];
|
||||
struct efx_mae *mae;
|
||||
|
||||
unsigned int xdp_tx_queue_count;
|
||||
struct efx_tx_queue **xdp_tx_queues;
|
||||
|
Loading…
x
Reference in New Issue
Block a user