common/sfc_efx/base: add API to read MAE mport journal
authorViacheslav Galaktionov <viacheslav.galaktionov@oktetlabs.ru>
Mon, 11 Oct 2021 14:48:49 +0000 (17:48 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 12 Oct 2021 16:44:11 +0000 (18:44 +0200)
This is required to provide the driver with the current state of mports.

Signed-off-by: Viacheslav Galaktionov <viacheslav.galaktionov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
drivers/common/sfc_efx/base/efx.h
drivers/common/sfc_efx/base/efx_mae.c
drivers/common/sfc_efx/base/efx_mcdi.h
drivers/common/sfc_efx/version.map

index 9961262..e77b297 100644 (file)
@@ -4205,6 +4205,42 @@ typedef struct efx_mport_id_s {
        uint32_t id;
 } efx_mport_id_t;
 
+typedef enum efx_mport_type_e {
+       EFX_MPORT_TYPE_NET_PORT = 0,
+       EFX_MPORT_TYPE_ALIAS,
+       EFX_MPORT_TYPE_VNIC,
+} efx_mport_type_t;
+
+typedef enum efx_mport_vnic_client_type_e {
+       EFX_MPORT_VNIC_CLIENT_FUNCTION = 1,
+       EFX_MPORT_VNIC_CLIENT_PLUGIN,
+} efx_mport_vnic_client_type_t;
+
+typedef struct efx_mport_desc_s {
+       efx_mport_id_t                  emd_id;
+       boolean_t                       emd_can_receive_on;
+       boolean_t                       emd_can_deliver_to;
+       boolean_t                       emd_can_delete;
+       boolean_t                       emd_zombie;
+       efx_mport_type_t                emd_type;
+       union {
+               struct {
+                       uint32_t        ep_index;
+               } emd_net_port;
+               struct {
+                       efx_mport_id_t  ea_target_mport_id;
+               } emd_alias;
+               struct {
+                       efx_mport_vnic_client_type_t    ev_client_type;
+                       efx_pcie_interface_t            ev_intf;
+                       uint16_t                        ev_pf;
+                       uint16_t                        ev_vf;
+                       /* MCDI client handle for this VNIC. */
+                       uint32_t                        ev_handle;
+               } emd_vnic;
+       };
+} efx_mport_desc_t;
+
 #define        EFX_MPORT_NULL                  (0U)
 
 /*
@@ -4635,6 +4671,26 @@ efx_mae_mport_free(
        __in                            efx_nic_t *enp,
        __in                            const efx_mport_id_t *mportp);
 
+typedef __checkReturn  efx_rc_t
+(efx_mae_read_mport_journal_cb)(
+       __in            void *cb_datap,
+       __in            efx_mport_desc_t *mportp,
+       __in            size_t mport_len);
+
+/*
+ * Read mport descriptions from the MAE journal (which describes added and
+ * removed mports) and pass them to a user-supplied callback. The user gets
+ * only one chance to process the data it's given. Once the callback function
+ * finishes, that particular mport description will be gone.
+ * The journal will be fully repopulated on PCI reset (efx_nic_reset function).
+ */
+LIBEFX_API
+extern __checkReturn                   efx_rc_t
+efx_mae_read_mport_journal(
+       __in                            efx_nic_t *enp,
+       __in                            efx_mae_read_mport_journal_cb *cbp,
+       __in                            void *cb_datap);
+
 #endif /* EFSYS_OPT_MAE */
 
 #if EFSYS_OPT_VIRTIO
index 37cc48e..110addd 100644 (file)
@@ -3292,4 +3292,228 @@ fail1:
        return (rc);
 }
 
+static __checkReturn                   efx_rc_t
+efx_mae_read_mport_journal_single(
+       __in                            uint8_t *entry_buf,
+       __out                           efx_mport_desc_t *desc)
+{
+       uint32_t pcie_intf;
+       efx_rc_t rc;
+
+       memset(desc, 0, sizeof (*desc));
+
+       desc->emd_id.id = MCDI_STRUCT_DWORD(entry_buf,
+           MAE_MPORT_DESC_V2_MPORT_ID);
+
+       desc->emd_can_receive_on = MCDI_STRUCT_DWORD_FIELD(entry_buf,
+           MAE_MPORT_DESC_V2_FLAGS,
+           MAE_MPORT_DESC_V2_CAN_RECEIVE_ON);
+
+       desc->emd_can_deliver_to = MCDI_STRUCT_DWORD_FIELD(entry_buf,
+           MAE_MPORT_DESC_V2_FLAGS,
+           MAE_MPORT_DESC_V2_CAN_DELIVER_TO);
+
+       desc->emd_can_delete = MCDI_STRUCT_DWORD_FIELD(entry_buf,
+           MAE_MPORT_DESC_V2_FLAGS,
+           MAE_MPORT_DESC_V2_CAN_DELETE);
+
+       desc->emd_zombie = MCDI_STRUCT_DWORD_FIELD(entry_buf,
+           MAE_MPORT_DESC_V2_FLAGS,
+           MAE_MPORT_DESC_V2_IS_ZOMBIE);
+
+       desc->emd_type = MCDI_STRUCT_DWORD(entry_buf,
+           MAE_MPORT_DESC_V2_MPORT_TYPE);
+
+       /*
+        * We can't check everything here. If some additional checks are
+        * required, they should be performed by the callback function.
+        */
+       switch (desc->emd_type) {
+       case EFX_MPORT_TYPE_NET_PORT:
+               desc->emd_net_port.ep_index =
+                   MCDI_STRUCT_DWORD(entry_buf,
+                       MAE_MPORT_DESC_V2_NET_PORT_IDX);
+               break;
+       case EFX_MPORT_TYPE_ALIAS:
+               desc->emd_alias.ea_target_mport_id.id =
+                   MCDI_STRUCT_DWORD(entry_buf,
+                       MAE_MPORT_DESC_V2_ALIAS_DELIVER_MPORT_ID);
+               break;
+       case EFX_MPORT_TYPE_VNIC:
+               desc->emd_vnic.ev_client_type =
+                   MCDI_STRUCT_DWORD(entry_buf,
+                       MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE);
+               if (desc->emd_vnic.ev_client_type !=
+                   EFX_MPORT_VNIC_CLIENT_FUNCTION)
+                       break;
+
+               pcie_intf = MCDI_STRUCT_DWORD(entry_buf,
+                   MAE_MPORT_DESC_V2_VNIC_FUNCTION_INTERFACE);
+               rc = efx_mcdi_intf_from_pcie(pcie_intf,
+                   &desc->emd_vnic.ev_intf);
+               if (rc != 0)
+                       goto fail1;
+
+               desc->emd_vnic.ev_pf = MCDI_STRUCT_WORD(entry_buf,
+                   MAE_MPORT_DESC_V2_VNIC_FUNCTION_PF_IDX);
+               desc->emd_vnic.ev_vf = MCDI_STRUCT_WORD(entry_buf,
+                   MAE_MPORT_DESC_V2_VNIC_FUNCTION_VF_IDX);
+               desc->emd_vnic.ev_handle = MCDI_STRUCT_DWORD(entry_buf,
+                   MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE);
+               break;
+       default:
+               rc = EINVAL;
+               goto fail2;
+       }
+
+       return (0);
+
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+       return (rc);
+}
+
+static __checkReturn                   efx_rc_t
+efx_mae_read_mport_journal_batch(
+       __in                            efx_nic_t *enp,
+       __in                            efx_mae_read_mport_journal_cb *cbp,
+       __in                            void *cb_datap,
+       __out                           uint32_t *morep)
+{
+       efx_mcdi_req_t req;
+       EFX_MCDI_DECLARE_BUF(payload,
+           MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN,
+           MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2);
+       uint32_t n_entries;
+       uint32_t entry_sz;
+       uint8_t *entry_buf;
+       unsigned int i;
+       efx_rc_t rc;
+
+       EFX_STATIC_ASSERT(EFX_MPORT_TYPE_NET_PORT ==
+           MAE_MPORT_DESC_V2_MPORT_TYPE_NET_PORT);
+       EFX_STATIC_ASSERT(EFX_MPORT_TYPE_ALIAS ==
+           MAE_MPORT_DESC_V2_MPORT_TYPE_ALIAS);
+       EFX_STATIC_ASSERT(EFX_MPORT_TYPE_VNIC ==
+           MAE_MPORT_DESC_V2_MPORT_TYPE_VNIC);
+
+       EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_FUNCTION ==
+           MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_FUNCTION);
+       EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_PLUGIN ==
+           MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_PLUGIN);
+
+       if (cbp == NULL) {
+               rc = EINVAL;
+               goto fail1;
+       }
+
+       req.emr_cmd = MC_CMD_MAE_MPORT_READ_JOURNAL;
+       req.emr_in_buf = payload;
+       req.emr_in_length = MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN;
+       req.emr_out_buf = payload;
+       req.emr_out_length = MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2;
+
+       MCDI_IN_SET_DWORD(req, MAE_MPORT_READ_JOURNAL_IN_FLAGS, 0);
+
+       efx_mcdi_execute(enp, &req);
+
+       if (req.emr_rc != 0) {
+               rc = req.emr_rc;
+               goto fail2;
+       }
+
+       if (req.emr_out_length_used <
+           MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN) {
+               rc = EMSGSIZE;
+               goto fail3;
+       }
+
+       if (morep != NULL) {
+               *morep = MCDI_OUT_DWORD_FIELD(req,
+                   MAE_MPORT_READ_JOURNAL_OUT_FLAGS,
+                   MAE_MPORT_READ_JOURNAL_OUT_MORE);
+       }
+       n_entries = MCDI_OUT_DWORD(req,
+           MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT);
+       entry_sz = MCDI_OUT_DWORD(req,
+           MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC);
+       entry_buf = MCDI_OUT2(req, uint8_t,
+           MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA);
+
+       if (entry_sz < MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_OFST +
+           MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_LEN) {
+               rc = EINVAL;
+               goto fail4;
+       }
+       if (n_entries * entry_sz / entry_sz != n_entries) {
+               rc = EINVAL;
+               goto fail5;
+       }
+       if (req.emr_out_length_used !=
+           MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN + n_entries * entry_sz) {
+               rc = EINVAL;
+               goto fail6;
+       }
+
+       for (i = 0; i < n_entries; i++) {
+               efx_mport_desc_t desc;
+
+               rc = efx_mae_read_mport_journal_single(entry_buf, &desc);
+               if (rc != 0)
+                       continue;
+
+               (*cbp)(cb_datap, &desc, sizeof (desc));
+               entry_buf += entry_sz;
+       }
+
+       return (0);
+
+fail6:
+       EFSYS_PROBE(fail6);
+fail5:
+       EFSYS_PROBE(fail5);
+fail4:
+       EFSYS_PROBE(fail4);
+fail3:
+       EFSYS_PROBE(fail3);
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+       return (rc);
+}
+
+       __checkReturn                   efx_rc_t
+efx_mae_read_mport_journal(
+       __in                            efx_nic_t *enp,
+       __in                            efx_mae_read_mport_journal_cb *cbp,
+       __in                            void *cb_datap)
+{
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+       uint32_t more = 0;
+       efx_rc_t rc;
+
+       if (encp->enc_mae_supported == B_FALSE) {
+               rc = ENOTSUP;
+               goto fail1;
+       }
+
+       do {
+               rc = efx_mae_read_mport_journal_batch(enp, cbp, cb_datap,
+                   &more);
+               if (rc != 0)
+                       goto fail2;
+       } while (more != 0);
+
+       return (0);
+
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+       return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
index 90b70de..96f237b 100644 (file)
@@ -462,6 +462,60 @@ efx_mcdi_phy_module_get_info(
        EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +         \
                        (_idx)), _field)
 
+#define        MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, _type, _arr_ofst, _idx,    \
+               _member_ofst)                                           \
+       ((_type *)(MCDI_OUT2(_emr, uint8_t, _arr_ofst) +                \
+                  _idx * MC_CMD_ ## _arr_ofst ## _LEN +                \
+                  _member_ofst ## _OFST))
+
+#define        MCDI_OUT_INDEXED_MEMBER_DWORD(_emr, _arr_ofst, _idx,            \
+               _member_ofst)                                           \
+       EFX_DWORD_FIELD(                                                \
+               *(MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, efx_dword_t,     \
+                                                _arr_ofst, _idx,       \
+                                                _member_ofst)),        \
+               EFX_DWORD_0)
+
+#define        MCDI_OUT_INDEXED_MEMBER_QWORD(_emr, _arr_ofst, _idx,            \
+               _member_ofst)                                           \
+       ((uint64_t)EFX_QWORD_FIELD(                                     \
+               *(MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, efx_qword_t,     \
+                                                _arr_ofst, _idx,       \
+                                                _member_ofst)),        \
+               EFX_DWORD_0) |                                          \
+       (uint64_t)EFX_QWORD_FIELD(                                      \
+               *(MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, efx_qword_t,     \
+                                                _arr_ofst, _idx,       \
+                                                _member_ofst)),        \
+               EFX_DWORD_1) << 32)
+
+#define MCDI_STRUCT_MEMBER(_buf, _type, _ofst)                         \
+       ((_type *)((char *)_buf + _ofst ## _OFST))      \
+
+#define MCDI_STRUCT_BYTE(_buf, _ofst)                                  \
+       EFX_BYTE_FIELD(*MCDI_STRUCT_MEMBER(_buf, efx_byte_t, _ofst),    \
+                      EFX_BYTE_0)
+
+#define MCDI_STRUCT_BYTE_FIELD(_buf, _ofst, _field)                    \
+       EFX_BYTE_FIELD(*MCDI_STRUCT_MEMBER(_buf, efx_byte_t, _ofst),    \
+                      _field)
+
+#define MCDI_STRUCT_WORD(_buf, _ofst)                                  \
+       EFX_WORD_FIELD(*MCDI_STRUCT_MEMBER(_buf, efx_word_t, _ofst),    \
+                      EFX_WORD_0)
+
+#define MCDI_STRUCT_WORD_FIELD(_buf, _ofst, _field)                    \
+       EFX_WORD_FIELD(*MCDI_STRUCT_MEMBER(_buf, efx_word_t, _ofst),    \
+                      _field)
+
+#define MCDI_STRUCT_DWORD(_buf, _ofst)                                 \
+       EFX_DWORD_FIELD(*MCDI_STRUCT_MEMBER(_buf, efx_dword_t, _ofst),  \
+                       EFX_DWORD_0)
+
+#define MCDI_STRUCT_DWORD_FIELD(_buf, _ofst, _field)                   \
+       EFX_DWORD_FIELD(*MCDI_STRUCT_MEMBER(_buf, efx_dword_t, _ofst),  \
+                       _field)
+
 #define        MCDI_EV_FIELD(_eqp, _field)                                     \
        EFX_QWORD_FIELD(*_eqp, MCDI_EVENT_ ## _field)
 
index 2259098..10216bb 100644 (file)
@@ -133,6 +133,7 @@ INTERNAL {
        efx_mae_mport_invalid;
        efx_mae_outer_rule_insert;
        efx_mae_outer_rule_remove;
+       efx_mae_read_mport_journal;
 
        efx_mcdi_fini;
        efx_mcdi_get_proxy_handle;