sfc: add ndo_set_vf_link_state() function for EF10
authorEdward Cree <ecree@solarflare.com>
Wed, 20 May 2015 10:12:13 +0000 (11:12 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 21 May 2015 22:43:54 +0000 (18:43 -0400)
Exercised with
"ip link set <PF intf> vf <vf_i> state {auto|enable|disable}"
Sets the reporting policy for VF link state to either
 - mirror physical link state
 - always up
 - always down

get VF link state mode in efx_ef10_sriov_get_vf_config

Exercised by
"ip link show <PF intf>";
output will include a line like
vf 0 MAC 12:34:56:78:9a:bc, link-state auto

Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/ef10_sriov.c
drivers/net/ethernet/sfc/ef10_sriov.h
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi_pcol.h
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/sriov.c
drivers/net/ethernet/sfc/sriov.h

index 525808f34036b5de786d78cb0c51bbf63bebb70e..e624ddd87d16cca85cc0d18bed5c3be0d00b0ad0 100644 (file)
@@ -4135,6 +4135,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
        .sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan,
        .sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk,
        .sriov_get_vf_config = efx_ef10_sriov_get_vf_config,
+       .sriov_set_vf_link_state = efx_ef10_sriov_set_vf_link_state,
        .vswitching_probe = efx_ef10_vswitching_probe_pf,
        .vswitching_restore = efx_ef10_vswitching_restore_pf,
        .vswitching_remove = efx_ef10_vswitching_remove_pf,
index 49238fc5f0f1d9db1dc22187d13149ae689219be..edc34f39fa3ad819bc8ca6a78000d8540225e460 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;
 }
index 0428265bcff98f51d25b46fec5e62b84116d88cc..91393a69b89fa3fa86f6519ab23f9a297b8fc310 100644 (file)
@@ -58,6 +58,9 @@ static inline int efx_ef10_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf,
 int efx_ef10_sriov_get_vf_config(struct efx_nic *efx, int vf_i,
                                 struct ifla_vf_info *ivf);
 
+int efx_ef10_sriov_set_vf_link_state(struct efx_nic *efx, int vf_i,
+                                    int link_state);
+
 int efx_ef10_vswitching_probe_pf(struct efx_nic *efx);
 int efx_ef10_vswitching_probe_vf(struct efx_nic *efx);
 int efx_ef10_vswitching_restore_pf(struct efx_nic *efx);
index 0ca6e77055305480c08825aedf18032e191c1542..8cacb96a1dfa59dcec51b775986b227080f9f6fe 100644 (file)
@@ -2281,6 +2281,7 @@ static const struct net_device_ops efx_netdev_ops = {
        .ndo_set_vf_vlan        = efx_sriov_set_vf_vlan,
        .ndo_set_vf_spoofchk    = efx_sriov_set_vf_spoofchk,
        .ndo_get_vf_config      = efx_sriov_get_vf_config,
+       .ndo_set_vf_link_state  = efx_sriov_set_vf_link_state,
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = efx_netpoll,
index fc50be78293fc943af2b4b97eb6c85170f30dc9d..30f580157b761b1a798defb3343f3be81c258090 100644 (file)
 #define          MC_CMD_GET_WORKAROUNDS_OUT_BUG35017 0x8
 
 
+/***********************************/
+/* MC_CMD_LINK_STATE_MODE
+ * Read/set link state mode of a VF
+ */
+#define MC_CMD_LINK_STATE_MODE 0x5c
+
+#define MC_CMD_0x5c_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_LINK_STATE_MODE_IN msgrequest */
+#define    MC_CMD_LINK_STATE_MODE_IN_LEN 8
+/* The target function to have its link state mode read or set, must be a VF
+ * e.g. VF 1,3 = 0x00030001
+ */
+#define       MC_CMD_LINK_STATE_MODE_IN_FUNCTION_OFST 0
+#define        MC_CMD_LINK_STATE_MODE_IN_FUNCTION_PF_LBN 0
+#define        MC_CMD_LINK_STATE_MODE_IN_FUNCTION_PF_WIDTH 16
+#define        MC_CMD_LINK_STATE_MODE_IN_FUNCTION_VF_LBN 16
+#define        MC_CMD_LINK_STATE_MODE_IN_FUNCTION_VF_WIDTH 16
+/* New link state mode to be set */
+#define       MC_CMD_LINK_STATE_MODE_IN_NEW_MODE_OFST 4
+#define          MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_AUTO       0x0 /* enum */
+#define          MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_UP         0x1 /* enum */
+#define          MC_CMD_LINK_STATE_MODE_IN_LINK_STATE_DOWN       0x2 /* enum */
+/* enum: Use this value to just read the existing setting without modifying it.
+ */
+#define          MC_CMD_LINK_STATE_MODE_IN_DO_NOT_CHANGE         0xffffffff
+
+/* MC_CMD_LINK_STATE_MODE_OUT msgresponse */
+#define    MC_CMD_LINK_STATE_MODE_OUT_LEN 4
+#define       MC_CMD_LINK_STATE_MODE_OUT_OLD_MODE_OFST 0
+
+
 /***********************************/
 /* MC_CMD_READ_REGS
  * Get a dump of the MCPU registers
index 364217b81aaf398a894139be85a8f5b0f33aa09c..c2eabd9fd5150e762cb8cd0e102ed38a6436b4ff 100644 (file)
@@ -1348,6 +1348,8 @@ struct efx_nic_type {
                                     bool spoofchk);
        int (*sriov_get_vf_config)(struct efx_nic *efx, int vf_i,
                                   struct ifla_vf_info *ivi);
+       int (*sriov_set_vf_link_state)(struct efx_nic *efx, int vf_i,
+                                      int link_state);
        int (*vswitching_probe)(struct efx_nic *efx);
        int (*vswitching_restore)(struct efx_nic *efx);
        void (*vswitching_remove)(struct efx_nic *efx);
index d4b74452a67767b283b856672859733351f0959e..6c5edbdbfa27edaa29a0d7d0b281447387d56c66 100644 (file)
@@ -58,3 +58,15 @@ int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i,
        else
                return -EOPNOTSUPP;
 }
+
+int efx_sriov_set_vf_link_state(struct net_device *net_dev, int vf_i,
+                               int link_state)
+{
+       struct efx_nic *efx = netdev_priv(net_dev);
+
+       if (efx->type->sriov_set_vf_link_state)
+               return efx->type->sriov_set_vf_link_state(efx, vf_i,
+                                                         link_state);
+       else
+               return -EOPNOTSUPP;
+}
index 0b9f0f6acf3b0f68ccb7ae3db078c858fd322f9b..3be15a54c562d7eb176fb7657bd976a4634cf59a 100644 (file)
@@ -21,6 +21,8 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf_i,
                              bool spoofchk);
 int efx_sriov_get_vf_config(struct net_device *net_dev, int vf_i,
                            struct ifla_vf_info *ivi);
+int efx_sriov_set_vf_link_state(struct net_device *net_dev, int vf_i,
+                               int link_state);
 
 #endif /* CONFIG_SFC_SRIOV */