aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-07-08 19:07:34 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-08 19:07:34 -0400
commit4df48e8c0e9f210f54bcf975aa6c39cf67672781 (patch)
tree16dff7897a89df2fd934d73dc960057603aa406e
parentb5a983f3141239b5b0b4a4e66efa31f8a26354b8 (diff)
parent535a61777f44eebcb71f2a6866f95b17ee0f13c7 (diff)
Merge branch 'sfc-set-mac'
Shradha Shah says: ==================== sfc: compat for lack of VADAPTOR_SET_MAC in adaptor_firmware <= 4.1.1.1023 This patch series resolves an incompatibility with legacy firmware due to the lack of MC_CMD_VADAPTOR_SET_MAC in adaptor_firmware <= 4.1.1.1023 Unless this patch series is applied there will be a compatibility issue between the driver and Solarflare adapters running older firmware. Tested with and without CONFIG_SFC_SRIOV ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/sfc/ef10.c172
-rw-r--r--drivers/net/ethernet/sfc/ef10_sriov.c42
-rw-r--r--drivers/net/ethernet/sfc/ef10_sriov.h6
3 files changed, 151 insertions, 69 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 847643455468..605cc8948594 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -101,6 +101,11 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)
101 return resource_size(&efx->pci_dev->resource[bar]); 101 return resource_size(&efx->pci_dev->resource[bar]);
102} 102}
103 103
104static bool efx_ef10_is_vf(struct efx_nic *efx)
105{
106 return efx->type->is_vf;
107}
108
104static int efx_ef10_get_pf_index(struct efx_nic *efx) 109static int efx_ef10_get_pf_index(struct efx_nic *efx)
105{ 110{
106 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN); 111 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
@@ -677,6 +682,48 @@ static int efx_ef10_probe_pf(struct efx_nic *efx)
677 return efx_ef10_probe(efx); 682 return efx_ef10_probe(efx);
678} 683}
679 684
685int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
686{
687 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
688
689 MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
690 return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
691 NULL, 0, NULL);
692}
693
694int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
695{
696 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
697
698 MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
699 return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
700 NULL, 0, NULL);
701}
702
703int efx_ef10_vport_add_mac(struct efx_nic *efx,
704 unsigned int port_id, u8 *mac)
705{
706 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
707
708 MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
709 ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
710
711 return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
712 sizeof(inbuf), NULL, 0, NULL);
713}
714
715int efx_ef10_vport_del_mac(struct efx_nic *efx,
716 unsigned int port_id, u8 *mac)
717{
718 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
719
720 MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
721 ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
722
723 return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
724 sizeof(inbuf), NULL, 0, NULL);
725}
726
680#ifdef CONFIG_SFC_SRIOV 727#ifdef CONFIG_SFC_SRIOV
681static int efx_ef10_probe_vf(struct efx_nic *efx) 728static int efx_ef10_probe_vf(struct efx_nic *efx)
682{ 729{
@@ -3804,6 +3851,72 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
3804 WARN_ON(remove_failed); 3851 WARN_ON(remove_failed);
3805} 3852}
3806 3853
3854static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
3855{
3856 struct efx_ef10_nic_data *nic_data = efx->nic_data;
3857 u8 mac_old[ETH_ALEN];
3858 int rc, rc2;
3859
3860 /* Only reconfigure a PF-created vport */
3861 if (is_zero_ether_addr(nic_data->vport_mac))
3862 return 0;
3863
3864 efx_device_detach_sync(efx);
3865 efx_net_stop(efx->net_dev);
3866 down_write(&efx->filter_sem);
3867 efx_ef10_filter_table_remove(efx);
3868 up_write(&efx->filter_sem);
3869
3870 rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id);
3871 if (rc)
3872 goto restore_filters;
3873
3874 ether_addr_copy(mac_old, nic_data->vport_mac);
3875 rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id,
3876 nic_data->vport_mac);
3877 if (rc)
3878 goto restore_vadaptor;
3879
3880 rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id,
3881 efx->net_dev->dev_addr);
3882 if (!rc) {
3883 ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
3884 } else {
3885 rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old);
3886 if (rc2) {
3887 /* Failed to add original MAC, so clear vport_mac */
3888 eth_zero_addr(nic_data->vport_mac);
3889 goto reset_nic;
3890 }
3891 }
3892
3893restore_vadaptor:
3894 rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
3895 if (rc2)
3896 goto reset_nic;
3897restore_filters:
3898 down_write(&efx->filter_sem);
3899 rc2 = efx_ef10_filter_table_probe(efx);
3900 up_write(&efx->filter_sem);
3901 if (rc2)
3902 goto reset_nic;
3903
3904 rc2 = efx_net_open(efx->net_dev);
3905 if (rc2)
3906 goto reset_nic;
3907
3908 netif_device_attach(efx->net_dev);
3909
3910 return rc;
3911
3912reset_nic:
3913 netif_err(efx, drv, efx->net_dev,
3914 "Failed to restore when changing MAC address - scheduling reset\n");
3915 efx_schedule_reset(efx, RESET_TYPE_DATAPATH);
3916
3917 return rc ? rc : rc2;
3918}
3919
3807static int efx_ef10_set_mac_address(struct efx_nic *efx) 3920static int efx_ef10_set_mac_address(struct efx_nic *efx)
3808{ 3921{
3809 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN); 3922 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
@@ -3820,8 +3933,8 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
3820 efx->net_dev->dev_addr); 3933 efx->net_dev->dev_addr);
3821 MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID, 3934 MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
3822 nic_data->vport_id); 3935 nic_data->vport_id);
3823 rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf, 3936 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
3824 sizeof(inbuf), NULL, 0, NULL); 3937 sizeof(inbuf), NULL, 0, NULL);
3825 3938
3826 efx_ef10_filter_table_probe(efx); 3939 efx_ef10_filter_table_probe(efx);
3827 up_write(&efx->filter_sem); 3940 up_write(&efx->filter_sem);
@@ -3829,38 +3942,27 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
3829 efx_net_open(efx->net_dev); 3942 efx_net_open(efx->net_dev);
3830 netif_device_attach(efx->net_dev); 3943 netif_device_attach(efx->net_dev);
3831 3944
3832#if !defined(CONFIG_SFC_SRIOV) 3945#ifdef CONFIG_SFC_SRIOV
3833 if (rc == -EPERM) 3946 if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
3834 netif_err(efx, drv, efx->net_dev,
3835 "Cannot change MAC address; use sfboot to enable mac-spoofing"
3836 " on this interface\n");
3837#else
3838 if (rc == -EPERM) {
3839 struct pci_dev *pci_dev_pf = efx->pci_dev->physfn; 3947 struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
3840 3948
3841 /* Switch to PF and change MAC address on vport */ 3949 if (rc == -EPERM) {
3842 if (efx->pci_dev->is_virtfn && pci_dev_pf) { 3950 struct efx_nic *efx_pf;
3843 struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
3844 3951
3845 if (!efx_ef10_sriov_set_vf_mac(efx_pf, 3952 /* Switch to PF and change MAC address on vport */
3846 nic_data->vf_index, 3953 efx_pf = pci_get_drvdata(pci_dev_pf);
3847 efx->net_dev->dev_addr))
3848 return 0;
3849 }
3850 netif_err(efx, drv, efx->net_dev,
3851 "Cannot change MAC address; use sfboot to enable mac-spoofing"
3852 " on this interface\n");
3853 } else if (efx->pci_dev->is_virtfn) {
3854 /* Successfully changed by VF (with MAC spoofing), so update the
3855 * parent PF if possible.
3856 */
3857 struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
3858 3954
3859 if (pci_dev_pf) { 3955 rc = efx_ef10_sriov_set_vf_mac(efx_pf,
3956 nic_data->vf_index,
3957 efx->net_dev->dev_addr);
3958 } else if (!rc) {
3860 struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf); 3959 struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
3861 struct efx_ef10_nic_data *nic_data = efx_pf->nic_data; 3960 struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
3862 unsigned int i; 3961 unsigned int i;
3863 3962
3963 /* MAC address successfully changed by VF (with MAC
3964 * spoofing) so update the parent PF if possible.
3965 */
3864 for (i = 0; i < efx_pf->vf_count; ++i) { 3966 for (i = 0; i < efx_pf->vf_count; ++i) {
3865 struct ef10_vf *vf = nic_data->vf + i; 3967 struct ef10_vf *vf = nic_data->vf + i;
3866 3968
@@ -3871,8 +3973,24 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
3871 } 3973 }
3872 } 3974 }
3873 } 3975 }
3874 } 3976 } else
3875#endif 3977#endif
3978 if (rc == -EPERM) {
3979 netif_err(efx, drv, efx->net_dev,
3980 "Cannot change MAC address; use sfboot to enable"
3981 " mac-spoofing on this interface\n");
3982 } else if (rc == -ENOSYS && !efx_ef10_is_vf(efx)) {
3983 /* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC
3984 * fall-back to the method of changing the MAC address on the
3985 * vport. This only applies to PFs because such versions of
3986 * MCFW do not support VFs.
3987 */
3988 rc = efx_ef10_vport_set_mac_address(efx);
3989 } else {
3990 efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC,
3991 sizeof(inbuf), NULL, 0, rc);
3992 }
3993
3876 return rc; 3994 return rc;
3877} 3995}
3878 3996
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c
index 6c9b6e45509a..7485f71b4e2f 100644
--- a/drivers/net/ethernet/sfc/ef10_sriov.c
+++ b/drivers/net/ethernet/sfc/ef10_sriov.c
@@ -29,30 +29,6 @@ static int efx_ef10_evb_port_assign(struct efx_nic *efx, unsigned int port_id,
29 NULL, 0, NULL); 29 NULL, 0, NULL);
30} 30}
31 31
32static int efx_ef10_vport_add_mac(struct efx_nic *efx,
33 unsigned int port_id, u8 *mac)
34{
35 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
36
37 MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
38 ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
39
40 return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
41 sizeof(inbuf), NULL, 0, NULL);
42}
43
44static int efx_ef10_vport_del_mac(struct efx_nic *efx,
45 unsigned int port_id, u8 *mac)
46{
47 MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
48
49 MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
50 ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
51
52 return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
53 sizeof(inbuf), NULL, 0, NULL);
54}
55
56static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id, 32static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
57 unsigned int vswitch_type) 33 unsigned int vswitch_type)
58{ 34{
@@ -136,24 +112,6 @@ static int efx_ef10_vport_free(struct efx_nic *efx, unsigned int port_id)
136 NULL, 0, NULL); 112 NULL, 0, NULL);
137} 113}
138 114
139static int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
140{
141 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
142
143 MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
144 return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
145 NULL, 0, NULL);
146}
147
148static int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
149{
150 MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
151
152 MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
153 return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
154 NULL, 0, NULL);
155}
156
157static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx) 115static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
158{ 116{
159 struct efx_ef10_nic_data *nic_data = efx->nic_data; 117 struct efx_ef10_nic_data *nic_data = efx->nic_data;
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.h b/drivers/net/ethernet/sfc/ef10_sriov.h
index db4ef537c610..6d25b92cb45e 100644
--- a/drivers/net/ethernet/sfc/ef10_sriov.h
+++ b/drivers/net/ethernet/sfc/ef10_sriov.h
@@ -65,5 +65,11 @@ int efx_ef10_vswitching_restore_pf(struct efx_nic *efx);
65int efx_ef10_vswitching_restore_vf(struct efx_nic *efx); 65int efx_ef10_vswitching_restore_vf(struct efx_nic *efx);
66void efx_ef10_vswitching_remove_pf(struct efx_nic *efx); 66void efx_ef10_vswitching_remove_pf(struct efx_nic *efx);
67void efx_ef10_vswitching_remove_vf(struct efx_nic *efx); 67void efx_ef10_vswitching_remove_vf(struct efx_nic *efx);
68int efx_ef10_vport_add_mac(struct efx_nic *efx,
69 unsigned int port_id, u8 *mac);
70int efx_ef10_vport_del_mac(struct efx_nic *efx,
71 unsigned int port_id, u8 *mac);
72int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id);
73int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id);
68 74
69#endif /* EF10_SRIOV_H */ 75#endif /* EF10_SRIOV_H */