sfc: add ndo_set_vf_link_state() function for EF10
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / sfc / ef10_sriov.c
index 49238fc..edc34f3 100644 (file)
@@ -667,11 +667,37 @@ reset_nic:
        return rc ? rc : rc2;
 }
 
+int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i,
+                                    int link_state)
+{
+       MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN);
+       struct efx_ef10_nic_data *nic_data = efx->nic_data;
+
+       BUILD_BUG_ON(IFLA_VF_LINK_STATE_AUTO !=
+                    MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_AUTO);
+       BUILD_BUG_ON(IFLA_VF_LINK_STATE_ENABLE !=
+                    MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_UP);
+       BUILD_BUG_ON(IFLA_VF_LINK_STATE_DISABLE !=
+                    MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_DOWN);
+       MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION,
+                             LINK_STATE_MODE_IN_FUNCTION_PF,
+                             nic_data->pf_index,
+                             LINK_STATE_MODE_IN_FUNCTION_VF, vf_i);
+       MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE, link_state);
+       return efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf),
+                           NULL, 0, NULL); /* don't care what old mode was */
+}
+
 int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
                                 struct ifla_vf_info *ivf)
 {
+       MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_STATE_MODE_IN_LEN);
+       MCDI_DECLARE_BUF(outbuf, MC_CMD_LINK_STATE_MODE_OUT_LEN);
+
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
        struct ef10_vf *vf;
+       size_t outlen;
+       int rc;
 
        if (vf_i >= efx->vf_count)
                return -EINVAL;
@@ -688,5 +714,19 @@ int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
        ivf->vlan = (vf->vlan == EFX_EF10_NO_VLAN) ? 0 : vf->vlan;
        ivf->qos = 0;
 
+       MCDI_POPULATE_DWORD_2(inbuf, LINK_STATE_MODE_IN_FUNCTION,
+                             LINK_STATE_MODE_IN_FUNCTION_PF,
+                             nic_data->pf_index,
+                             LINK_STATE_MODE_IN_FUNCTION_VF, vf_i);
+       MCDI_SET_DWORD(inbuf, LINK_STATE_MODE_IN_NEW_MODE,
+                      MC_CMD_LINK_STATE_MODE_IN_DO_NOT_CHANGE);
+       rc = efx_mcdi_rpc(efx, MC_CMD_LINK_STATE_MODE, inbuf, sizeof(inbuf),
+                         outbuf, sizeof(outbuf), &outlen);
+       if (rc)
+               return rc;
+       if (outlen < MC_CMD_LINK_STATE_MODE_OUT_LEN)
+               return -EIO;
+       ivf->linkstate = MCDI_DWORD(outbuf, LINK_STATE_MODE_OUT_OLD_MODE);
+
        return 0;
 }